Initial MSVC 2008 projects workspace

This commit is contained in:
alexey.min
2012-02-01 05:25:08 +00:00
commit 03de3bdc95
1446 changed files with 476853 additions and 0 deletions

31
l2packets/AionPackets.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef AIONPACKETS_H_
#define AIONPACKETS_H_
/** \file AionPackets.h
* Main include file to include all library files related to Aion.
*/
// detect OS
#if defined(_WIN32) || defined(WIN32) || defined(WINVER) || defined(_WIN32_WINNT)
#undef L2PACKETS_WINDOWS
#define L2PACKETS_WINDOWS
#else
#undef L2PACKETS_LINUX
#define L2PACKETS_LINUX
#endif
// base of library
#include "L2_versions.h"
#include "xcpt/L2Packets_xcpt.h"
#include "base/ByteArray.h"
#include "base/L2BasePacket.h"
// network
#include "net_io/L2Packet_NetLayer.h"
#include "net_io/L2PacketReceiver.h"
#include "net_io/L2PacketSender.h"
//#include "login/AionLoginPacket.h"
#include "game/AionGamePacket.h"
#endif /* AIONPACKETS_H_ */

97
l2packets/L2Packets.h Normal file
View File

@@ -0,0 +1,97 @@
#ifndef L2PACKETS_H_
#define L2PACKETS_H_
/** \file L2Packets.h
* Main include file to include all other library files related to Lineage II.
*/
// detect OS
#if defined(_WIN32) || defined(WIN32) || defined(WINVER) || defined(_WIN32_WINNT)
#undef L2PACKETS_WINDOWS
#define L2PACKETS_WINDOWS
#else
#undef L2PACKETS_LINUX
#define L2PACKETS_LINUX
#endif
/* some #defines come here
* they determine some behaviour of L2Packets library
*
* L2LOGINP_DEBUGOUT_BLOWFISH - if defined, library reports to stdout errors/successes
* about Blowfish encoding/decoding process of login server packets
* L2LOGINP_DEBUGOUT_XOR - if defined, library reports to stdout errors/successes about
* Init packet XOR decoding process
* L2LOGINP_DEBUGOUT_CHKSUM - if defined, library reports to stdout about process of
* appending checksum to login server packets
* L2LOGINP_DEBUGOUT_PADDING - if defined, library reports to stdout about process of
* padding login server packets to 8-byte boundary
*
* L2P_NETWORK_DEBUGOUT - debug messages about sending/receiving packets process
*/
// those should be defined in login/L2LoginPacket.h:
//#define L2LOGINP_DEBUGOUT_BLOWFISH
//#define L2LOGINP_DEBUGOUT_XOR
//#define L2LOGINP_DEBUGOUT_CHKSUM
//#define L2LOGINP_DEBUGOUT_PADDING
// these should be defined in net_io headers (in both)
//#define L2P_NETWORK_DEBUGOUT
#include "L2_versions.h"
#include "base/ByteArray.h"
#include "base/L2BasePacket.h"
#include "net_io/L2Packet_NetLayer.h"
#include "net_io/L2PacketReceiver.h"
#include "net_io/L2PacketSender.h"
#include "login/L2LoginPacket.h"
#include "login/server/L2Login_Init.h"
#include "login/client/L2Login_RequestGGAuth.h"
#include "login/server/L2Login_GGAuthResponse.h"
#include "login/client/L2Login_RequestAuthLogin.h"
#include "login/server/L2Login_LoginOK.h"
#include "login/server/L2Login_LoginFail.h"
#include "login/server/L2Login_AccountKicked.h"
#include "login/client/L2Login_RequestServerList.h"
#include "login/server/L2Login_ServerList.h"
#include "login/client/L2Login_RequestServerLogin.h"
#include "login/server/L2Login_PlayOK.h"
#include "login/server/L2Login_PlayFail.h"
#include "game/L2GamePacket.h"
// game: from server
#include "game/server/L2Game_AuthLoginFail.h"
#include "game/server/L2Game_CharCreateFail.h"
#include "game/server/L2Game_CharCreateSuccess.h"
#include "game/server/L2Game_CharDeleteFail.h"
#include "game/server/L2Game_CharDeleteSuccess.h"
#include "game/server/L2Game_CharSelected.h"
#include "game/server/L2Game_CharSelectionInfo.h"
#include "game/server/L2Game_KeyPacket.h"
#include "game/server/L2Game_NewCharacterSuccess.h"
#include "game/server/L2Game_SSQInfo.h"
// game: from client
#include "game/client/L2Game_Action.h"
#include "game/client/L2Game_AuthLogin.h"
#include "game/client/L2Game_CharacterCreate.h"
#include "game/client/L2Game_CharacterDelete.h"
#include "game/client/L2Game_CharacterRestore.h"
#include "game/client/L2Game_CharacterSelect.h"
#include "game/client/L2Game_EnterWorld.h"
#include "game/client/L2Game_NewCharacter.h"
#include "game/client/L2Game_ProtocolVersion.h"
#include "game/client/L2Game_RequestJoinParty.h"
#include "game/client/L2Game_RequestGotoLobby.h"
#include "game/client/L2Game_RequestUserCommand.h"
#include "game/client/L2Game_UseItem.h"
#include "pcode_obfuscator/L2PCodeObfuscator.h"
#include "l2data/L2Data.h"
#include "l2world/L2World.h"
#include "packetNames/L2PacketNames.h"
#include "xcpt/L2Packets_xcpt.h"
#endif /*L2PACKETS_H_*/

20
l2packets/L2_versions.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef H_L2_VERSIONS
#define H_L2_VERSIONS
typedef enum eL2_VERSION
{
/** constant to set protocol version as Kamael */
L2_VERSION_T1 = 0,
/** constant to set protocol version as Hellbound */
L2_VERSION_T15 = 1,
/** constant to set protocol version as Gracia Part 1 */
L2_VERSION_T2 = 2,
/** constant to set protocol version as Gracia Part 2 */
L2_VERSION_T22 = 3,
/** constant to set protocol version as Gracia Final */
L2_VERSION_T23 = 4,
/** constant to set protocol version as Gracia Epilogue */
L2_VERSION_T24 = 5
} L2_VERSION;
#endif

View File

@@ -0,0 +1,239 @@
#include "stdafx.h"
#include "ByteArray.h"
#include "../xcpt/L2Packets_xcpt.h"
#ifdef _DEBUG
int ByteArray::_debugPrintf( const char *_Format, ... )
{
if( !this->bDebugMode ) return 0;
if( !_Format ) return 0;
if( !this->fLogFile ) return 0;
va_list args;
int ret = 0;
va_start( args, _Format );
ret = vfprintf( this->fLogFile, _Format, args );
return ret;
}
void ByteArray::setDebugMode( bool bDebug, FILE *flog )
{
if( bDebug && flog )
{
this->bDebugMode = bDebug;
this->fLogFile = flog;
return;
}
if( !bDebug )
{
this->bDebugMode = false;
this->fLogFile = NULL;
}
}
void ByteArray::dumpArrayInfo( FILE * fOut )
{
if( !fOut ) return;
fprintf( fOut, "==== Dump of Array info ====\n" );
fprintf( fOut, " Size: %u\n", this->byteCount );
if( this->byteCount > 0 )
{
unsigned i = 0;
while( i < this->byteCount )
{
fprintf( fOut, "%c:%02X ", this->bytes[i], this->bytes[i] );
i++;
}
}
fprintf( fOut, "\n==== end dump ====\n" );
}
#endif
void ByteArray::_initNull()
{
// data
this->byteCount = 0;
this->bytes = NULL;
// debug mode vars
#ifdef _DEBUG
this->bDebugMode = false;
this->fLogFile = NULL;
#endif
}
void ByteArray::_freeSelf()
{
if( (this->byteCount > 0) && (this->bytes) )
{
free( this->bytes );
this->bytes = NULL;
this->byteCount = 0;
#ifdef _DEBUG
_debugPrintf( "ByteArray::_freeSelf() freeed\n" );
#endif
}
#ifdef _DEBUG
else _debugPrintf( "ByteArray::_freeSelf() nothing to free\n" );
#endif
}
ByteArray::ByteArray()
{
this->_initNull();
}
ByteArray::ByteArray( unsigned int length )
{
this->_initNull();
if( length > 0 ) this->setSize( length );
}
ByteArray::ByteArray( const char *string )
{
this->_initNull();
if( string ) this->setBytesFromString( string );
}
ByteArray::ByteArray( const unsigned char *newBytes, unsigned int length )
{
this->_initNull();
this->setBytes( newBytes, length );
}
ByteArray::ByteArray( const ByteArray& ba )
{
this->_initNull();
this->setBytes( ba.bytes, ba.byteCount );
}
ByteArray::~ByteArray()
{
this->_freeSelf();
#ifdef _DEBUG
_debugPrintf( "ByteArray::~ByteArray() worked\n" );
#endif
}
bool ByteArray::setSize( unsigned int newSize )
{
if( newSize == 0 )
{
this->_freeSelf();
return true;
}
if( newSize == this->byteCount ) return true; // already have that size
if( newSize > 0 )
{
unsigned char *newPtr = (unsigned char *)realloc( this->bytes, newSize );
if( newPtr )
{
this->bytes = newPtr;
this->byteCount = newSize;
return true;
}
#ifdef L2P_THROW
else throw L2P_MemoryError( "ByteArray::setSize()", newSize );
#else
return false;
#endif
}
return false;
}
unsigned char ByteArray::getByteAt( unsigned int index ) const
{
if( (this->byteCount > 0) && (this->bytes) )
{
if( index < (this->byteCount) ) return this->bytes[index];
return 0;
}
#ifdef L2P_THROW
throw L2P_ReadException( "ByteArray::getByteAt()", 1, (int)index, (int)byteCount );
#else
return 0;
#endif
}
unsigned char ByteArray::setByteAt( unsigned int index, unsigned char byteSet )
{
if( (this->byteCount > 0) && (this->bytes) )
{
unsigned char retVal = 0;
if( index < (this->byteCount) )
{
retVal = this->bytes[index];
this->bytes[index] = byteSet;
}
#ifdef L2P_THROW
else throw L2P_WriteException( "ByteArray::setByteAt()", 1, (int)index, (int)byteCount );
#endif
return retVal;
}
else
{
#ifdef L2P_THROW
throw L2P_WriteException( "ByteArray::setByteAt()", 1, (int)index, (int)byteCount );
#else
return 0;
#endif
}
}
void ByteArray::memset( unsigned char c )
{
if( (this->byteCount > 0) && (this->bytes) )
{
/*unsigned int i = 0;
while( i < this->byteCount )
this->bytes[i++] = c;*/
::memset( this->bytes, c, this->byteCount );
}
}
bool ByteArray::setBytes( const unsigned char *newBytes, unsigned int length )
{
if( length < 1 ) return false;
//unsigned int i = 0;
//
//printf( "ByteArray::setBytes( 0x%p, %u )\n", newBytes, length );
//printf( "ByteArray::setBytes(): %u < %u?\n", this->byteCount, length );
//
// check if it is enough space in 'bytes' now
if( this->byteCount < length ) // not enough
{
// we should try to grow to required size
if( !this->setSize( length ) ) return false; // growing failed :(
}
// if we're here, space in 'bytes' buffer is enough to hold 'length' bytes
this->memset( 0x00 );
//while( i < length ) this->bytes[i] = newBytes[i++];
memcpy( this->bytes, newBytes, length );
//printf( "ByteArray::setBytes(): %u bytes set OK (buffer len %u)\n", length, this->byteCount );
return true;
}
bool ByteArray::setBytesFromString( const char *string )
{
if( !string ) return false;
unsigned int str_len = strlen( string );
if( str_len < 1 ) return false;
return this->setBytes( (const unsigned char *)string, str_len );
}
bool ByteArray::setBytesFromPtrNoMemcpy( unsigned char *bytes, unsigned int length )
{
if( !bytes || (length<1) ) return false;
this->byteCount = length;
this->bytes = bytes;
return true;
}
unsigned char ByteArray::operator[]( int index ) const
{
if( (this->byteCount > 0) && (this->bytes) )
{
if( (index>=0) && (index<((int)(this->byteCount))) ) return this->bytes[index];
return 0;
}
return 0;
}

111
l2packets/base/ByteArray.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef H_BYTEARRAY
#define H_BYTEARRAY
/** \class ByteArray
* Represents array of bytes with variable size.\n
* L2Packets programmer does not work with ByteArray directly.
* This object is used inside L2BasePacket to hold raw packet data bytes.
*/
class ByteArray
{
public: // constructors/destructors
/** Default constructor with zero array length */
ByteArray();
/** Constructs ByteArray object with specified array length
* \param length - size in bytes to reserve space
*/
ByteArray( unsigned int length );
/** Constructs ByteArray object with length equal to length of string \n
* and with contents of this string. \n
* Calls setBytesFromString( string );
* \param string - string from which to set contents of created ByteArray
*/
ByteArray( const char *string );
/** Copy constructor */
ByteArray( const ByteArray& ba );
/** Constructs ByteArray object and sets its size and contents.
* \param newBytes pointer to data to set contents
* \param length data size
*/
ByteArray( const unsigned char *newBytes, unsigned int length );
~ByteArray();
public: // size funcs
/** \return Current array size. */
inline unsigned int getSize() const { return this->byteCount; }
/** sets new size of buffer. Contents remain unchanged (but may be truncated). \n
* In general, calls C runtime realloc()\n
* May throw L2P_MemoryError exception, if enabled.
* \param newSize new size of buffer. Must be >= 0
*/
bool setSize( unsigned int newSize );
public: // data functions
/** \return pointer to internal data buffer */
inline unsigned char *getBytesPtr() const { return this->bytes; }
/** Get byte value at specified index.\n
* May throw L2P_ReadException, if enabled.
* \param index Index of byte to retreive. If index is out of array bounds, function returns zero.
* \return byte alue at index, or 0 if index does not belong to array.
*/
unsigned char getByteAt( unsigned int index ) const;
/** Sets byte at specified index.\n
* May throw L2P_WriteException, if enabled.
* \param index Byte index to set. If index does not belong to array, function does nothing.
* \param byteSet new byte value
* \return previous byte value */
unsigned char setByteAt( unsigned int index, unsigned char byteSet );
/** Fills array with specified byte value.
* \param c value to assign to all bytes. */
void memset( unsigned char c );
/** Sets all array contents. Data is copied to internal storage
* \param newBytes data to set.
* \param length length of data. If length is > current array length, function resizes array to fit contents.
* \return true, if set was ok. false, if there were errors (memory failure?)
*/
bool setBytes( const unsigned char *newBytes, unsigned int length );
/** Sets array data from string data. Terminating zero is not appended.
* \param string string from which to copy bytes.
* \return true/false */
bool setBytesFromString( const char *string );
/** Sets internal pointer to data buffer and internal bytes counter from specified pointer to data and size.\n
* Data is not copied (works much faster)\n
* This function is not recommended to use, because:\n
* WARNING! buffer must be allocated by the same C runtime as library uses - malloc(), realloc(), calloc(). \n
* WARNING! object frees its buffer when destructor executes, so, free() will be called for source buffer.
* \param bytes data to set.
* \param length length of data. If length is > current array length, function resizes array to fit contents.
* \return true, if set was ok.*/
bool setBytesFromPtrNoMemcpy( unsigned char *bytes, unsigned int length );
public: // operators
/** Calls getByteAt( index ) */
unsigned char operator[]( int index ) const;
protected: // internal functions
void _initNull();
void _freeSelf();
// debug functions
#ifdef _DEBUG
public:
void setDebugMode( bool bDebug, FILE *flog );
int _debugPrintf( const char *_Format, ... );
void dumpArrayInfo( FILE * fOut );
#endif
protected:
// data
unsigned int byteCount; ///< internal array size counter
unsigned char *bytes; ///< internal pointer to allocated buffer
// debug mode vars
#ifdef _DEBUG
bool bDebugMode;
FILE *fLogFile;
#endif
};
#endif

View File

@@ -0,0 +1,650 @@
#include "stdafx.h"
#include "L2BasePacket.h"
#include "../xcpt/L2Packets_xcpt.h"
L2BasePacket::L2BasePacket()
{
this->_initNull();
}
L2BasePacket::L2BasePacket( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
L2BasePacket::~L2BasePacket()
{
_freeSelf();
}
bool L2BasePacket::setBytes( const unsigned char *bytes, unsigned int length )
{
_initNull();
if( !bytes || (length < 2) ) return false;
//
//printf( "L2BasePacket::setBytes( 0x%p, %u )\n", bytes, length );
//
this->ensureCanWriteBytes( length );
bool ret = this->b.setBytes( bytes, length );
if( ret )
{
this->buffer_size = b.getSize();
this->real_size = length;
this->datasize = length - 2; // length always >= 2 here
this->write_ptr = length;
this->read_ptr = 2;
// should we update packet size field in packet (0,1 bytes) here?, YES, imo
this->b.setByteAt( 0, (unsigned char)((length) & 0xff) );
this->b.setByteAt( 1, (unsigned char)((length >> 8) & 0xff) );
}
return ret;
}
bool L2BasePacket::setBytesPtr( unsigned char *bytes, unsigned int length )
{
if( !bytes || (length < 2) ) return false;
if( this->b.setBytesFromPtrNoMemcpy( bytes, length ) )
{
this->buffer_size = b.getSize();
this->real_size = length;
this->datasize = length - 2;
this->write_ptr = length;
this->read_ptr = 2;
// should we update packet size field in packet (0,1 bytes) here?, YES, imo
this->b.setByteAt( 0, (unsigned char)((length) & 0xff) );
this->b.setByteAt( 1, (unsigned char)((length >> 8) & 0xff) );
return true;
}
return false;
}
void L2BasePacket::setPacketType( unsigned char type )
{
writeReset();
writeUChar( type );
}
void L2BasePacket::setPacketType2( unsigned char opcode, unsigned short opcode2 )
{
writeReset();
writeUChar( opcode );
writeUShort( opcode2 );
}
void L2BasePacket::setPacketType3( unsigned char opcode, unsigned short opcode2, unsigned short opcode3 )
{
writeReset();
writeUChar( opcode );
writeUShort( opcode2 );
writeUShort( opcode3 );
}
/*unsigned char L2BasePacket::getPacketType()
{
readReset();
return readUChar();
}*/
/*unsigned short L2BasePacket::getPacketSize() const
{
return (unsigned short)(this->real_size);
}*/
/*unsigned short L2BasePacket::getDataSize() const// number of DATA bytes in packet
{
return (unsigned short)(this->datasize);
}*/
bool L2BasePacket::ensureCanWriteBytes( unsigned int nBytes )
{
if( nBytes == 0 ) return true;
unsigned int end_ptr = write_ptr + nBytes - 1; // calc write end pointer
// loop until end_ptr fits in buffer size
while( end_ptr >= buffer_size ) // not enough place in buffer
{
if( !this->_growBuffer() ) return false; // _growBuffer() increases buffer_size
}
return true;
}
void L2BasePacket::writeChar( char c )
{
if( !this->ensureCanWriteBytes( 1 ) ) return; // TODO: Throw exception??
this->b.setByteAt( this->write_ptr, (unsigned char)c );
this->write_ptr++;
this->real_size++;
this->datasize++;
// update packet size
// 1st 2 bytes contain only DATA size? no IMO
unsigned short psize = (unsigned short)real_size;
//unsigned short psize = (unsigned short)datasize;
unsigned char *psaddr = (unsigned char *)&psize;
b.setByteAt( 0, psaddr[0] );
b.setByteAt( 1, psaddr[1] );
}
void L2BasePacket::writeUChar( unsigned char c )
{
if( !this->ensureCanWriteBytes( 1 ) ) return; // TODO: Throw exception??
//printf( "L2BasePacket::writeUChar(): writing [0x%02X] at idx [%d]\n",
// (unsigned int)c, this->write_ptr );
this->b.setByteAt( this->write_ptr, c );
this->write_ptr++;
this->real_size++;
this->datasize++;
// update packet size
unsigned short psize = (unsigned short)real_size;
unsigned char *psaddr = (unsigned char *)&psize;
b.setByteAt( 0, psaddr[0] );
b.setByteAt( 1, psaddr[1] );
}
void L2BasePacket::writeBytes( const unsigned char *bytes, unsigned int len )
{
if( !bytes || (len<1) ) return;
unsigned int i;
for( i=0; i<len; i++ ) this->writeUChar( bytes[i] );
}
void L2BasePacket::writeShort( short int s )
{
char leftByte = (char)(s & 0x00FF);
char rightByte = (char)( (s & 0xFF00) >> 8 );
this->writeChar( leftByte );
this->writeChar( rightByte );
}
void L2BasePacket::writeUShort( unsigned short int s )
{
unsigned char leftByte = (unsigned char)( s & (unsigned short)0x00FF);
unsigned char rightByte = (unsigned char)( (s & (unsigned short)0xFF00) >> 8 );
this->writeUChar( leftByte );
this->writeUChar( rightByte );
}
void L2BasePacket::writeInt( int i )
{
char b1 = (char)( i & (int)0x000000FF);
char b2 = (char)( (i & (int)0x0000FF00) >> 8 );
char b3 = (char)( (i & (int)0x00FF0000) >> 16 );
char b4 = (char)( (i & (int)0xFF000000) >> 24 );
this->writeChar( b1 );
this->writeChar( b2 );
this->writeChar( b3 );
this->writeChar( b4 );
}
void L2BasePacket::writeUInt( unsigned int i )
{
unsigned char b1 = (unsigned char)( i & (unsigned int)0x000000FF);
unsigned char b2 = (unsigned char)( (i & (unsigned int)0x0000FF00) >> 8 );
unsigned char b3 = (unsigned char)( (i & (unsigned int)0x00FF0000) >> 16 );
unsigned char b4 = (unsigned char)( (i & (unsigned int)0xFF000000) >> 24 );
this->writeUChar( b1 );
this->writeUChar( b2 );
this->writeUChar( b3 );
this->writeUChar( b4 );
}
void L2BasePacket::writeInt64( long long int i64 )
{
char *i64b = (char *)(&i64);
unsigned int i;
for( i=0; i<sizeof(long long int); i++ ) this->writeChar( i64b[i] );
}
void L2BasePacket::writeUInt64( unsigned long long int i64 )
{
unsigned char *i64b = (unsigned char *)(&i64);
unsigned int i;
for( i=0; i<sizeof(unsigned long long int); i++ ) this->writeUChar( i64b[i] );
}
void L2BasePacket::writeDouble( double d )
{
char *pd = (char *)(&d);
unsigned int i;
for( i=0; i<sizeof(double); i++ ) this->writeChar( pd[i] );
}
void L2BasePacket::writeString( const char *str )
{
if( !str ) return;
char *p = (char *)str;
while( (*p) )
{
this->writeChar( (*p) );
p++;
}
this->writeChar( 0 );
}
void L2BasePacket::writeUnicodeString( const wchar_t *ustr )
{
if( !ustr ) return;
wchar_t *p = (wchar_t *)ustr;
while( (*p) )
{
this->writeShort( (*p) );
p++;
}
this->writeShort( 0x0000 );
}
bool L2BasePacket::canReadBytes( unsigned int nBytes )
{
if( nBytes == 0 ) return true;
unsigned int end_ptr = read_ptr + nBytes;
if( end_ptr <= real_size ) return true;
return false;
}
char L2BasePacket::readChar()
{
if( !canReadBytes( 1 ) )
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readChar()", 1, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
char ret = b.getByteAt( read_ptr );
read_ptr++;
return ret;
}
unsigned char L2BasePacket::readUChar()
{
if( !canReadBytes( 1 ) )
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUChar()", 1, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
unsigned char ret = b.getByteAt( read_ptr );
read_ptr++;
return ret;
}
bool L2BasePacket::readBytes( unsigned char *bytes, unsigned int num )
{
if( !bytes || (num<1) ) return false;
unsigned int i;
for( i=0; i<num; i++ ) bytes[i] = this->readUChar();
return true;
}
short int L2BasePacket::readShort()
{
if( canReadBytes( 2 ) )
{
unsigned char c1 = readChar();
unsigned char c2 = readChar();
unsigned short int ret = ((unsigned short int)c1) | ((unsigned short int)c2 << 8);
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readShort()", 2, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
unsigned short int L2BasePacket::readUShort()
{
if( canReadBytes( 2 ) )
{
unsigned char c1 = readUChar();
unsigned char c2 = readUChar();
unsigned short int ret = ((unsigned short int)c1) | ((unsigned short int)c2 << 8);
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUShort()", 2, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
int L2BasePacket::readInt()
{
if( canReadBytes( 4 ) )
{
unsigned char c1 = readChar();
unsigned char c2 = readChar();
unsigned char c3 = readChar();
unsigned char c4 = readChar();
unsigned int ret = (unsigned int)c1;
ret |= ( (unsigned int)c2 << 8 );
ret |= ( (unsigned int)c3 << 16 );
ret |= ( (unsigned int)c4 << 24 );
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readInt()", 4, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
unsigned int L2BasePacket::readUInt()
{
if( canReadBytes( 4 ) )
{
unsigned char c1 = readChar();
unsigned char c2 = readChar();
unsigned char c3 = readChar();
unsigned char c4 = readChar();
unsigned int ret = (unsigned int)c1;
ret |= ( (unsigned int)c2 << 8 );
ret |= ( (unsigned int)c3 << 16 );
ret |= ( (unsigned int)c4 << 24 );
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUInt()", 4, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
long long int L2BasePacket::readInt64()
{
long long int ret = 0;
if( this->canReadBytes( 8 ) )
{
unsigned int i;
unsigned char c = 0;
unsigned char *retaddr = (unsigned char *)&ret;
for( i=0; i<sizeof(long long int); i++ )
{
c = readChar();
(*retaddr) = c;
retaddr++;
}
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readInt64()", 8, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
unsigned long long int L2BasePacket::readUInt64()
{
unsigned long long int ret = 0;
if( this->canReadBytes( 8 ) )
{
unsigned int i;
unsigned char c = 0;
unsigned char *retaddr = (unsigned char *)&ret;
for( i=0; i<sizeof(unsigned long long int); i++ )
{
c = readUChar();
(*retaddr) = c;
retaddr++;
}
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUInt64()", 8, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
double L2BasePacket::readDouble()
{
double ret = 0.0;
if( canReadBytes( 8 ) )
{
unsigned int i = 0;
unsigned char c = 0;
unsigned char *retaddr = (unsigned char *)&ret;
for( i=0; i<sizeof(double); i++ )
{
c = readChar();
(*retaddr) = c;
retaddr++;
}
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readDouble()", 8, (int)read_ptr, (int)real_size );
#else
return 0.0;
#endif
}
char *L2BasePacket::readString()
{
unsigned int save_read_ptr = this->read_ptr;
unsigned int str_len = 0;
char c = 0;
char *str = NULL;
// count string length (including terminating 0x00 byte)
while( this->canReadBytes(1) )
{
c = this->readChar();
str_len++;
if( c == 0 ) break;
}
// restore read_ptr
this->read_ptr = save_read_ptr;
// assert
if( str_len == 0 ) return NULL;
// allocate buffer
str = (char *)malloc( str_len+1 ); // +1 for additional safety
if( !str ) return NULL;
str[str_len] = 0x00;
// read bytes to buffer
if( this->readBytes( (unsigned char *)str, str_len ) ) return str;
// some error? O_o
free( str );
str = NULL;
return NULL;
}
// returns allocated by malloc() buffer. must be freed later by caller!
wchar_t *L2BasePacket::readUnicodeString()
{
unsigned int save_read_ptr = this->read_ptr;
unsigned int str_len = 0;
unsigned int buffer_len = 0;
unsigned short int c = 0;
wchar_t *wstr = NULL;
// count string length (including terminating 0x0000 word)
while( this->canReadBytes(2) )
{
c = this->readUShort();
str_len++;
buffer_len += 2;
if( c == 0x0000 ) break;
}
// restore read_ptr
this->read_ptr = save_read_ptr;
// assert
if( str_len == 0 ) return NULL;
// allocate buffer
wstr = (wchar_t *)malloc( buffer_len+2 ); // +2 for more safety
if( !wstr ) return NULL;
wstr[str_len] = 0x0000;
// read bytes to buffer
if( this->readBytes( (unsigned char *)wstr, buffer_len ) ) return wstr;
// some error? O_o
free( wstr );
wstr = NULL;
return NULL;
}
// returns read-only pointer to wchar_t inside packet.
const wchar_t *L2BasePacket::readUnicodeStringPtr()
{
//unsigned int str_len = 0;
unsigned short int ch = 0;
// we return poiter to internal buffer
wchar_t *wstr = (wchar_t *)( this->getBytesPtr() + this->read_ptr );
// count string length (including terminating 0x0000 word), also moving current read_ptr
while( this->canReadBytes(2) )
{
ch = this->readUShort();
//str_len++;
//buffer_len += 2;
if( ch == 0x0000 ) break;
}
//wstr += str_len; // add counted string length to returned ptr
return wstr;
}
void L2BasePacket::writeReset()
{
write_ptr = 2; // pass 1st 2 bytes - packet size
real_size = 2; // think that only 2 bytes written
read_ptr = 2; // cannot read more than written :)
datasize = 0;
_preAllocateBuffer();
// update packet size field
b.setByteAt( 0, 2 );
b.setByteAt( 1, 0 );
}
void L2BasePacket::readReset()
{
read_ptr = 2; // pass 1st 2 bytes - packet size
}
bool L2BasePacket::_preAllocateBuffer()
{
if( !b.setSize( buffer_size ) ) return false; // TODO: or throw exception?
return true;
}
bool L2BasePacket::_growBuffer()
{
buffer_size *= 2;
return _preAllocateBuffer();
}
void L2BasePacket::_initNull()
{
buffer_size = 256;
datasize = 0;
writeReset();
readReset();
}
void L2BasePacket::_freeSelf()
{
buffer_size = 256;
writeReset();
readReset();
}
void L2BasePacket::dumpToFile( FILE *f )
{
if( !f ) return;
fprintf( f, "L2BasePacket::dumpToFile() begin\n" );
fprintf( f, "-- read_ptr : %u\n", this->read_ptr );
fprintf( f, "-- write_ptr : %u\n", this->write_ptr );
fprintf( f, "-- buffer_size : %u\n", this->buffer_size );
fprintf( f, "-- real_size : %u\n", this->real_size );
unsigned int psize = (unsigned int)(this->b[0]) |
( ((unsigned int)this->b[1]) << 8 );
fprintf( f, "-- Packet size : %u (%02X %02X)\n", psize, this->b[0], this->b[1] );
if( this->real_size > 2 )
{
fprintf( f, "-- Packet type : %u (%02X)\n", this->b.getByteAt( 2 ), this->b[2] );
fprintf( f, "-- ByteArray b :\n" );
unsigned int i = 0;
for( i=0; i<this->real_size; i++ )
fprintf( f, "%02X ", this->b[i] );
fprintf( f, "\n" );
}
fprintf( f, "L2BasePacket::dumpToFile() end\n\n" );
}
void L2BasePacket::saveToFileRaw( const char *filename )
{
if( !filename ) return;
FILE *f = fopen( filename, "wb" );
if( !f ) return;
fprintf( f, "L2BasePacket::dumpToFile() begin\r\n" );
fprintf( f, "-- read_ptr : %u\r\n", this->read_ptr );
fprintf( f, "-- write_ptr : %u\r\n", this->write_ptr );
fprintf( f, "-- buffer_size : %u\r\n", this->buffer_size );
fprintf( f, "-- real_size : %u\r\n", this->real_size );
unsigned int psize = this->b[0] + (this->b[1] << 8);
fprintf( f, "-- Packet size : %u (%02X %02X)\r\n", psize, this->b[0], this->b[1] );
if( this->real_size > 2 )
{
unsigned char *bytes = b.getBytesPtr();
unsigned int count = b.getSize();
fwrite( bytes, 1, count, f );
}
fprintf( f, "L2BasePacket::dumpToFile() end\n\n" );
fclose( f );
}
void L2BasePacket::displaySelfNice( FILE *f )
{
this->dumpToFile( f );
}
unsigned char L2BasePacket::getByteAt( unsigned int index )
{
if( index >= real_size )
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::getByteAt()", 1, (int)index, (int)real_size );
#else
return 0;
#endif
char c = b.getByteAt( index );
return c;
}
unsigned char L2BasePacket::setByteAt( unsigned int index, unsigned char byte )
{
// checks are inside of ByteArray::setByteAt() (throwing exceptions if enabled)
return b.setByteAt( index, byte );
}
inline const unsigned char *L2BasePacket::getBytesPtr() const
{
return b.getBytesPtr();
}
/*L2BasePacket::operator const unsigned char *() const
{
return this->getBytesPtr();
}*/
ByteArray *L2BasePacket::readB( unsigned int count )
{
ByteArray *pByteArray = new ByteArray();
if( !pByteArray ) return NULL;
pByteArray->setSize( count );
if( this->readBytes( pByteArray->getBytesPtr(), count ) ) return pByteArray;
delete pByteArray;
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readB()", (int)count, (int)read_ptr, (int)real_size );
#else
return NULL;
#endif
}
// must be overrided in child classes
bool L2BasePacket::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
this->readReset();
this->readUChar();
return true;
}
// must be overrided in child classes
bool L2BasePacket::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
this->writeReset();
return true;
}

View File

@@ -0,0 +1,284 @@
#ifndef H_L2BASEPACKET
#define H_L2BASEPACKET
#include "ByteArray.h"
#include "../L2_versions.h"
#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(x) // will produce compiler warnings, anyway
#endif
/** \class L2BasePacket
* Represents base class for all L2 packets. Provides way to create packets,
* write data to packets, read data from them.\n
* Internally uses ByteArray object to hold raw packet data bytes.
* Allows writing data/reading data from packet, using readXXXX or writeXXXX functions.\n
* \n
* In Lineage protocol, all packets start with 2 bytes, which hold all packet length (including these first 2 bytes).
* These 2 bytes are never encrypted, so client application receives first 2 bytes,
* treates them as packet length and then reads the rest length-2 bytes.\n
* \n
* L2BasePacket internally uses ByteArray object to hold packet data. Initially created L2BasePacket object
* has preallocated space for 256 bytes in its internal storage (ByteArray::setSize(256)), so most write
* operations do not cause packet to grow. If 256 bytes is not enough, L2BasePacket automatically doubles
* size of its internal buffer, and so on.\n
* \n
* \n
*<pre>
* Lineage II packet structure:\n
* Size field packet data
* |----------------------|--------------------------|
* | low byte | high byte | opcode | ... ... ... ... |
* |----------------------|--------------------------|
* 0 1 2 3 .......... << byte ordinal numbers
* </pre>
* \n
* Size field is 16-bit integer, defines size of ALL packet, including size field itself. So,
* maximum length of L2 packet is 65536 bytes (maximum data size is 65534).
*/
class L2BasePacket
{
public:
/** Default constructor for empty packet. Preallocates buffer size for 256 bytes. */
L2BasePacket();
/** Copies length bytes to packet */
L2BasePacket( const unsigned char *bytes, unsigned int length ); // does memcpy()
/** Frees object memory */
virtual ~L2BasePacket();
public:
/** Reads byte at index from internal storage. Calls ByteArray::getByteAt()\n
* May throw L2P_ReadException in case of range error.
\param index - byte index to read
\return byte value, or 0 if index is out of range.
*/
virtual unsigned char getByteAt( unsigned int index );
/** Sets byte at specified index to value. Does nothing if index out of bounds. Calls ByteArray::setByteAt()\n
* May throw L2P_WriteException in case of range error.
* \param index byte index
* \param byte byte value to set
* \return previous byte value
*/
virtual unsigned char setByteAt( unsigned int index, unsigned char byte );
/** Copies bytes to internal storage buffer. Resizes internal buffer if needed. Calls ByteArray::setBytes()
* \param bytes pointer to source data buffer to copy from
* \param length source buffer size
* \return success state
*/
virtual bool setBytes( const unsigned char *bytes, unsigned int length );
/** Sets internal ByteArray's buffer pointer to [bytes], and length to [length]. Does no memcpy()\n
* Do not use this function!
* \param bytes pointer to new data buffer
* \param length source buffer size
* \return success state
* \see ByteArray::setBytesFromPtrNoMemcpy() */
virtual bool setBytesPtr( unsigned char *bytes, unsigned int length );
/** Sets 3rd byte of packet (which holds packet opcode).
* Equivalent to call writeReset() and writeUChar() with parameter type.
* Moves write pointer to byte #3 (next after opcode)
* \param type new packet opcode. */
virtual void setPacketType( unsigned char type );
/** Sets 3rd,4th,5th bytes of packet (which holds packet opcode and extended opcode).
* Equivalent to call writeReset(); writeUChar(); writeUShort() with parameter type.
* Moves write pointer!
* \param opcode new packet opcode.
* \param opcode2 extended opcode. */
virtual void setPacketType2( unsigned char opcode, unsigned short opcode2 );
/** Sets 3rd,4th,5th,6th,7th bytes of packet (which holds packet opcode, ext opcode, ext opcode 2).
* Equivalent to call writeReset(); writeUChar(); writeUShort() writeUShort() with parameter type.
* Moves write pointer!
* \param opcode new packet opcode.
* \param opcode2 extended opcode.
* \param opcode3 extended opcode 2.
*/
virtual void setPacketType3( unsigned char opcode, unsigned short opcode2, unsigned short opcode3 );
/** Reads packet opcode. Moves read pointer to byte #3 (next after opcode). Equivalent calls: readReset(); readUChar()
* \return read packet opcode. */
virtual unsigned char getPacketType() { readReset(); return readUChar(); }
/** Gets packet length in bytes (not size of internal data buffer, which is larger)
* \return packet lentgh */
virtual unsigned short getPacketSize() const { return (unsigned short)(this->real_size); }
/** Gets number of data bytes in packet (excluding 1st 2 bytes, which hold all packet size).
* Equivalent to getPacketSize()-2.
* \return number of <b>data</b> bytes in buffer. */
virtual unsigned short getDataSize() const { return (unsigned short)(this->datasize); }
public: // write funcs
// All of read/write funcs can throw subclasses of L2P_Exception in case of read/write errors.
/** Checks if it is possible to write nBytes bytes to packet; if no, tries to increase buffer size.
* Called automatically from write-functions.
* \param nBytes checked size
* \return false on memory error */
virtual bool ensureCanWriteBytes( unsigned int nBytes );
/** Moves write pointer to the beginning of the packet, to byte #2, where starts opcode.
* First 2 bytes (byte #0, byte #1 - packet size) are always updated automatically, and
* they cannot be accessed by read/write-functions, only by setByteAt() / getByteAt().
* Pre-allocates internal buffer, sets packet size to 2. */
virtual void writeReset();
/** Writes single byte to packet. Moves write pointer one char right
* \param c byte to write to packet. */
virtual void writeChar( char c );
/** Writes single byte to packet. Moves write pointer one char right
* \param c byte to write to packet. */
virtual void writeUChar( unsigned char c );
/** Writes short integer to packet. Moves write pointer two chars right
* \param s value to write to packet. */
virtual void writeShort( short int s );
/** Writes short integer to packet. Moves write pointer two chars right
* \param s value to write to packet. */
virtual void writeUShort( unsigned short int s );
/** Writes 32-bit integer to packet. Moves write pointer 4 chars right
* \param i value to write to packet. */
virtual void writeInt( int i );
/** Writes 32-bit integer to packet. Moves write pointer 4 chars right
* \param i value to write to packet. */
virtual void writeUInt( unsigned int i );
/** Writes 64-bit integer to packet. Moves write pointer 8 chars right
* \param i64 value to write to packet. */
virtual void writeInt64( long long int i64 );
/** Writes 64-bit integer to packet. Moves write pointer 8 chars right
* \param i64 value to write to packet. */
virtual void writeUInt64( unsigned long long int i64 );
/** Writes double value to packet. Moves write pointer 8 chars right
* \param d value to write to packet. */
virtual void writeDouble( double d );
/** Writes ANSI string to packet, also NULL terminator. Moves write pointer right by string length
* \param str string to write to packet. */
virtual void writeString( const char *str );
/** Writes Unicode string to packet, also Unicode NULL terminator. Moves write pointer right by string length*2
* \param ustr string to write to packet. */
virtual void writeUnicodeString( const wchar_t *ustr );
/** Writes bytes array to packet (len bytes). Moves write pointer right by len bytes
* \param bytes pointer to data to write to packet.
* \param len data length. */
virtual void writeBytes( const unsigned char *bytes, unsigned int len );
public: // read funcs
// All of read/write funcs can throw subclasses of L2P_Exception in case of read/write errors.
/** Checks if there are some bytes left to read form current read position in packet.
* \param nBytes number of bytes to test to readability.
* \return true, if nBytes bytes can be read form current read position; false if there are less than
* nBytes left in buffer. */
virtual bool canReadBytes( unsigned int nBytes );
/** Moves read pointer to byte #2 (opcode will be read next). */
virtual void readReset();
/** Reads one byte from packet. Moves read pointer to next position
* \return byte */
virtual char readChar();
/** Reads one byte from packet. Moves read pointer to next position
* \return byte */
virtual unsigned char readUChar();
/** Reads 16-bit integer from packet. Moves read pointer to next position
* \return short int */
virtual short int readShort();
/** Reads 16-bit integer from packet. Moves read pointer to next position
* \return short int */
virtual unsigned short int readUShort();
/** Reads 32-bit integer from packet. Moves read pointer to next position
* \return int */
virtual int readInt();
/** Reads 32-bit integer from packet. Moves read pointer to next position
* \return int */
virtual unsigned int readUInt();
/** Reads 64-bit integer from packet. Moves read pointer to next position
* \return long long int */
virtual long long int readInt64();
/** Reads 64-bit integer from packet. Moves read pointer to next position
* \return long long int */
virtual unsigned long long int readUInt64();
/** Reads double value from packet. Moves read pointer to next position
* \return double */
virtual double readDouble();
/** Reads ANSI string from packet. Moves read pointer to next read position
* \return pointer to allocated string */
virtual char *readString();
/** Reads Unicode string from packet. Moves read pointer to next read position. Allocates buffer.
* \return pointer to allocated string. Calling function must free() this buffer. */
virtual wchar_t *readUnicodeString();
/** Reads Unicode string from packet. Moves read pointer to next read position.\n
* Function does not allocate buffer,
* it just returns casted to (wchar_t *) pointer to internal data buffer as read-only.\n
* Warning! Returning pointer will be invalid, because internal data buffer is freed when object is destroyed.\n
* Warning! Data is read-only.\n
* This function may be faster than readUnicodeString() because it does not do
* memory allocation.
* \return pointer to allocated string */
virtual const wchar_t *readUnicodeStringPtr();
/** Reads num bytes from packet
* \param bytes pointer to buffer to store data
* \param num number of bytes to read
* \returns success state */
virtual bool readBytes( unsigned char *bytes, unsigned int num );
public: // L2J aliases
// writers
/** Alias to writeChar() */
virtual inline void writeC( char c ) { writeChar( c ); }
/** Alias to writeShort() */
virtual inline void writeH( short h ) { writeShort( h ); }
/** Alias to writeInt() */
virtual inline void writeD( int d ) { writeInt( d ); }
/** Alias to writeInt64() */
virtual inline void writeQ( long long int Q ) { writeInt64( Q ); }
/** Alias to writeDouble() */
virtual inline void writeF( double f ) { writeDouble( f ); }
/** Alias to writeUnicodeString() */
virtual inline void writeS( const wchar_t *string ) { writeUnicodeString( string ); }
/** Alias to writeBytes() */
virtual inline void writeB( const ByteArray& bytes ) { writeBytes( bytes.getBytesPtr(), bytes.getSize() ); }
// readers
/** Alias to readChar() */
virtual inline char readC() { return readChar(); }
/** Alias to readShort() */
virtual inline short readH() { return readShort(); }
/** Alias to readInt() */
virtual inline int readD() { return readInt(); }
/** Alias to readDouble() */
virtual inline double readF() { return readDouble(); }
/** Alias to readInt64() */
virtual inline long long int readQ() { return readInt64(); }
/** Alias to readUnicodeString() */
virtual inline wchar_t *readS() { return readUnicodeString(); }
/** Alias to readBytes() */
virtual ByteArray *readB( unsigned int count ); // not inline :)
public: // parsers/creators
/** Parses packet. Must be overriden in child classes */
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
/** Default method to create packet. Must be overriden in subclasses */
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
// DEBUG funcs
public:
/** Writes packet dump to file f n HEX
* \param f - file to write to */
virtual void dumpToFile( FILE *f );
/** Saves all packet to file as binary data
* \param filename - file name to save to */
virtual void saveToFileRaw( const char *filename );
/** here calls dumpToFile(). Must be overriden in child classes
* \param f - file to write to */
virtual void displaySelfNice( FILE *f );
public: // typeconv
//virtual operator const unsigned char *() const;
/** Returns pointer to all internal data buffer. Calls ByteArray::getBytesPtr()
* \return pointer to all internal data buffer */
virtual const unsigned char *getBytesPtr() const;
protected:
/** Internal function - called from constuctors. Initializes object state:
* Sets buffer_size to 256, calls readReset(), writeReset() */
virtual void _initNull();
/** Internal function. Pre-allocates internal buffer to buffer_size */
virtual bool _preAllocateBuffer();
/** Internal function. Tries to increase buffer size twice */
virtual bool _growBuffer();
/** almost the same as _initNull()... */
virtual void _freeSelf();
protected:
unsigned int buffer_size; ///< current buffer size
unsigned int real_size; ///< number of used bytes in buffer
unsigned int write_ptr; ///< index of next byte that will be written to buffer
unsigned int read_ptr; ///< index of next byte that will be read from buffer
unsigned int datasize; ///< number of data bytes in packet (excluding first 2 bytes that hold packet size)
ByteArray b; ///< internal buffer to hold raw packet data
};
#endif

View File

@@ -0,0 +1,181 @@
#include "stdafx.h"
#include "AionGamePacket.h"
unsigned char *AionGamePacket::STATIC_XOR_KEY = NULL;
void AionGamePacket::_checkInitStaticXorKey()
{
if( !AionGamePacket::STATIC_XOR_KEY )
AionGamePacket::STATIC_XOR_KEY = (unsigned char *)"nKO/WctQ0AVLbpzfBkS6NevDYT8ourG5CRlmdjyJ72aswx4EPq1UgZhFMXH?3iI9";
}
AionGamePacket::AionGamePacket()
{
this->_initNull();
this->_checkInitStaticXorKey();
}
AionGamePacket::AionGamePacket( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->_checkInitStaticXorKey();
this->setBytes( bytes, length );
}
bool AionGamePacket::decodeXOR( unsigned char *key )
{
if( !key ) return false;
bool r = AionGamePacket::decodeXOR_buffer( b.getBytesPtr(), getPacketSize(), key );
return r;
}
bool AionGamePacket::encodeXOR( unsigned char *key )
{
if( !key ) return false;
bool r = AionGamePacket::encodeXOR_buffer( b.getBytesPtr(), getPacketSize(), key );
return r;
}
bool AionGamePacket::decodeXOR_buffer( unsigned char *decodeBytes, unsigned int bytesLen, unsigned char *key )
{
if( !key ) return false;
const int data_offset = 2; // do not touch 1st 2 bytes - with packet length; pass them
unsigned int i = 0;
unsigned char cur = 0; // current byte
unsigned char prev = decodeBytes[data_offset]; // prev. encrypted byte
decodeBytes[data_offset] ^= key[0]; // decrypt 1st byte
// decrypt loop
for( i=(data_offset + 1); i<bytesLen; i++ )
{
cur = decodeBytes[i];
decodeBytes[i] ^= AionGamePacket::STATIC_XOR_KEY[(i-data_offset) & 63] ^ key[(i-data_offset) & 7] ^ prev;
prev = cur;
}
// old key value as 64-bit unsigned int
unsigned long long oldKey = (unsigned long long)key[0] | ((unsigned long long)key[1] << 8) |
((unsigned long long)key[2] << 16) | ((unsigned long long)key[3] << 24) |
((unsigned long long)key[4] << 32) | ((unsigned long long)key[5] << 40) |
((unsigned long long)key[6] << 48) | ((unsigned long long)key[7] << 56);
// packet size is added to old key value
oldKey += (bytesLen - 2); // data size = whole packet length - 2
// update key
key[0] = (unsigned char)(oldKey & 0xFF);
key[1] = (unsigned char)((oldKey >> 8) & 0xFF);
key[2] = (unsigned char)((oldKey >> 16) & 0xFF);
key[3] = (unsigned char)((oldKey >> 24) & 0xFF);
key[4] = (unsigned char)((oldKey >> 32) & 0xFF);
key[5] = (unsigned char)((oldKey >> 40) & 0xFF);
key[6] = (unsigned char)((oldKey >> 48) & 0xFF);
key[7] = (unsigned char)((oldKey >> 56) & 0xFF);
return true;
}
bool AionGamePacket::encodeXOR_buffer( unsigned char *encodeBytes, unsigned int bytesLen, unsigned char *key )
{
if( !key ) return false;
unsigned int i = 0;
unsigned char prev = 0; // prev. encoded byte
const int data_offset = 2; // do not touch 1st 2 bytes - with packet length; pass them
// encrypt 1st byte
encodeBytes[data_offset] ^= key[0];
prev = encodeBytes[data_offset];
// encrypt loop
for( i=(data_offset+1); i<bytesLen; i++ )
{
encodeBytes[i] ^= AionGamePacket::STATIC_XOR_KEY[(i-data_offset) & 63] ^ key[(i-data_offset) & 7] ^ prev;
prev = encodeBytes[i];
}
// old key value as 64-bit unsigned int
unsigned long long oldKey = (unsigned long long)key[0] | ((unsigned long long)key[1] << 8) |
((unsigned long long)key[2] << 16) | ((unsigned long long)key[3] << 24) |
((unsigned long long)key[4] << 32) | ((unsigned long long)key[5] << 40) |
((unsigned long long)key[6] << 48) | ((unsigned long long)key[7] << 56);
// packet size is added to old key value
oldKey += (bytesLen - 2); // data size = whole packet length - 2
// update key
key[0] = (unsigned char)(oldKey & 0xFF);
key[1] = (unsigned char)((oldKey >> 8) & 0xFF);
key[2] = (unsigned char)((oldKey >> 16) & 0xFF);
key[3] = (unsigned char)((oldKey >> 24) & 0xFF);
key[4] = (unsigned char)((oldKey >> 32) & 0xFF);
key[5] = (unsigned char)((oldKey >> 40) & 0xFF);
key[6] = (unsigned char)((oldKey >> 48) & 0xFF);
key[7] = (unsigned char)((oldKey >> 56) & 0xFF);
return true;
}
unsigned char AionGamePacket::obfuscateServerOpcode( unsigned char opcode )
{
return ((opcode + 0xAE) ^ 0xEE);
}
unsigned char AionGamePacket::deobfuscateServerOpcode( unsigned char opcode )
{
return ((opcode ^ 0xEE) - 0xAE);
}
bool AionGamePacket::writeServerOpcode( unsigned char opcode )
{
writeReset();
unsigned char scrambled_opcode = obfuscateServerOpcode( opcode );
writeUChar( scrambled_opcode );
writeUChar( AionGamePacket::STATIC_SERVER_OPCODE );
writeUChar( ~scrambled_opcode );
return true;
}
// TODO: verify this
bool AionGamePacket::writeClientOpcode( unsigned char opcode )
{
writeReset();
unsigned char scrambled_opcode = obfuscateServerOpcode( opcode ); // REALLYY??????????
writeUChar( scrambled_opcode ); // ARE YOU SURE??
writeUChar( AionGamePacket::STATIC_CLIENT_OPCODE );
writeUChar( ~scrambled_opcode );
return true;
}
bool AionGamePacket::validateClientOpcode() const
{
if( getDataSize() >= 3 )
{
unsigned char o1 = b[2];
unsigned char o2 = b[3];
unsigned char o3 = b[4];
if( (o1 == (unsigned char)(~o3)) && (o2 == AionGamePacket::STATIC_CLIENT_OPCODE) ) return true;
}
return false;
}
bool AionGamePacket::validateServerOpcode() const
{
if( getDataSize() >= 3 )
{
unsigned char o1 = b[2];
unsigned char o2 = b[3];
unsigned char o3 = b[4];
if( (o1 == (unsigned char)(~o3)) && (o2 == AionGamePacket::STATIC_SERVER_OPCODE) ) return true;
}
return false;
}
void AionGamePacket::initStaticXORKey( unsigned char *key )
{
key[4] = 0xA1;
key[5] = 0x6C;
key[6] = 0x54;
key[7] = 0x87;
}
unsigned char AionGamePacket::readOpcode()
{
unsigned char opcode = 0;
readReset();
if( canReadBytes( 3 ) )
{
opcode = readUChar();
readUChar(); // static opcode
readUChar(); // ~opcode
}
return opcode;
}

View File

@@ -0,0 +1,58 @@
#ifndef AIONGAMEPACKET_H_
#define AIONGAMEPACKET_H_
#include "../base/L2BasePacket.h"
class AionGamePacket : public L2BasePacket
{
public:
static const unsigned char STATIC_SERVER_OPCODE = 0x54;
static const unsigned char STATIC_CLIENT_OPCODE = 0x5D;
static unsigned char *STATIC_XOR_KEY;
//(const unsigned char *)"nKO/WctQ0AVLbpzfBkS6NevDYT8ourG5CRlmdjyJ72aswx4EPq1UgZhFMXH?3iI9";
public:
AionGamePacket();
AionGamePacket( const unsigned char *bytes, unsigned int length );
public:
/* Decodes this packet data with Aion XORgame encryption. key is updated at every dec/enc call
* \param key - 8-byte lenght key buffer */
bool decodeXOR( unsigned char *key );
/* Encodes this packet data with Aion XORgame encryption. key is updated at every dec/enc call
* \param key - 8-byte lenght key buffer */
bool encodeXOR( unsigned char *key );
/* Decodes buffer contents with Aion XOR game encryption. key is updated at every dec/enc call
* \param decodeBytes pointer to data to be decrypted
* \param bytesLen data length in bytes
* \param key - 8-byte lenght key buffer */
static bool decodeXOR_buffer( unsigned char *decodeBytes, unsigned int bytesLen, unsigned char *key );
/* Encodes buffer contents with Aion XOR game encryption. key is updated at every dec/enc call
* \param decodeBytes pointer to data to be decrypted
* \param bytesLen data length in bytes
* \param key - 8-byte lenght key buffer */
static bool encodeXOR_buffer( unsigned char *encodeBytes, unsigned int bytesLen, unsigned char *key );
public:
static unsigned char obfuscateServerOpcode( unsigned char opcode );
static unsigned char deobfuscateServerOpcode( unsigned char opcode );
bool writeServerOpcode( unsigned char opcode );
bool writeClientOpcode( unsigned char opcode );
bool validateServerOpcode() const;
bool validateClientOpcode() const;
unsigned char readOpcode();
public:
/** Creates initial XOR key - sets last 4 bytes of key. First 4 bytes are dynamic, last 4 bytes are const.\n
* key must point to 8-byte buffer.
* \param key 8-byte buffer; function updates last 4 of them. */
static void initStaticXORKey( unsigned char *key );
protected:
void _checkInitStaticXorKey();
};
#endif /* AIONGAMEPACKET_H_ */

View File

@@ -0,0 +1,153 @@
#include "stdafx.h"
#include "L2GamePacket.h"
L2GamePacket::L2GamePacket()
{
this->_initNull();
}
L2GamePacket::L2GamePacket( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
// in Hellbound key must be 16-byte array
// key is changed after enc/dec procedure
bool L2GamePacket::decodeXOR( unsigned char *key )
{
if( !key ) return false;
unsigned int sz = this->getPacketSize();
unsigned int dsz = this->getDataSize();
if( sz < 3 ) return false;
unsigned char temp = 0, temp2 = 0;
unsigned int i = 0;
unsigned char *data = (unsigned char *)this->getBytesPtr();
// xor enc/dec from index 2 (pass 2 bytes - packet size)
data += 2;
for( i = 0; i < dsz; i++ )
{
temp2 = data[i];
data[i] = (temp2 ^ (key[i & 15]) ^ temp);
temp = temp2;
}
unsigned int old = 0;
old |= key[8] & 0x000000ff;
old |= (key[9] << 0x08) & 0x0000ff00;
old |= (key[10] << 0x10) & 0x00ff0000;
old |= (key[11] << 0x18) & 0xff000000;
//old += sz;
old += dsz; // key increases by data size
key[8] = (unsigned char)((old) & 0xff);
key[9] = (unsigned char)((old >> 0x08) & 0xff);
key[10] = (unsigned char)((old >> 0x10) & 0xff);
key[11] = (unsigned char)((old >> 0x18) & 0xff);
return true;
}
// in Hellbound key must be 16-byte array
// key is changed after enc/dec procedure
bool L2GamePacket::encodeXOR( unsigned char *key )
{
if( !key ) return false;
unsigned int sz = this->getPacketSize();
unsigned int dsz = this->getDataSize();
if( sz < 3 ) return false;
unsigned char temp = 0, temp2 = 0;
unsigned int i = 0;
unsigned char *data = (unsigned char *)this->getBytesPtr();
// xor enc/dec from index 2 (pass 2 bytes - packet size)
data += 2;
for( i = 0; i < dsz; i++ )
{
temp2 = data[i];
data[i] = (temp2 ^ (key[i & 15]) ^ temp );
temp = data[i];
}
unsigned int old = 0;
old |= key[8] & 0x000000ff;
old |= (key[9] << 0x08) & 0x0000ff00;
old |= (key[10] << 0x10) & 0x00ff0000;
old |= (key[11] << 0x18) & 0xff000000;
//old += sz;
old += dsz; // key increases by data size
key[8] = (unsigned char)((old) & 0xff);
key[9] = (unsigned char)((old >> 0x08) & 0xff);
key[10] = (unsigned char)((old >> 0x10) & 0xff);
key[11] = (unsigned char)((old >> 0x18) & 0xff);
return true;
}
bool L2GamePacket::decodeXOR_buffer( unsigned char *decodeBytes, unsigned int bytesLen,
unsigned char *key )
{
//if( !key ) return false;
unsigned int dsz = bytesLen - 2;
//if( sz < 3 ) return false;
unsigned char temp = 0, temp2 = 0;
unsigned int i = 0;
unsigned char *data = decodeBytes;
// xor enc/dec from index 2 (pass 2 bytes - packet size)
data += 2;
for( i = 0; i < dsz; i++ )
{
temp2 = data[i];
data[i] = (temp2 ^ (key[i & 15]) ^ temp);
temp = temp2;
}
unsigned int old = 0;
old |= key[8] & 0x000000ff;
old |= (key[9] << 0x08) & 0x0000ff00;
old |= (key[10] << 0x10) & 0x00ff0000;
old |= (key[11] << 0x18) & 0xff000000;
//old += sz;
old += dsz; // key increases by data size
key[8] = (unsigned char)((old) & 0xff);
key[9] = (unsigned char)((old >> 0x08) & 0xff);
key[10] = (unsigned char)((old >> 0x10) & 0xff);
key[11] = (unsigned char)((old >> 0x18) & 0xff);
return true;
}
bool L2GamePacket::encodeXOR_buffer( unsigned char *encodeBytes, unsigned int bytesLen,
unsigned char *key )
{
//if( !key ) return false;
unsigned int dsz = bytesLen - 2;
//if( sz < 3 ) return false;
unsigned char temp = 0, temp2 = 0;
unsigned int i = 0;
unsigned char *data = encodeBytes;
// xor enc/dec from index 2 (pass 2 bytes - packet size)
data += 2;
for( i = 0; i < dsz; i++ )
{
temp2 = data[i];
data[i] = (temp2 ^ (key[i & 15]) ^ temp );
temp = data[i];
}
unsigned int old = 0;
old |= key[8] & 0x000000ff;
old |= (key[9] << 0x08) & 0x0000ff00;
old |= (key[10] << 0x10) & 0x00ff0000;
old |= (key[11] << 0x18) & 0xff000000;
//old += sz;
old += dsz; // key increases by data size
key[8] = (unsigned char)((old) & 0xff);
key[9] = (unsigned char)((old >> 0x08) & 0xff);
key[10] = (unsigned char)((old >> 0x10) & 0xff);
key[11] = (unsigned char)((old >> 0x18) & 0xff);
return true;
}

View File

@@ -0,0 +1,24 @@
#ifndef L2GAMEPACKET_H_
#define L2GAMEPACKET_H_
#include "../base/L2BasePacket.h"
class L2GamePacket : public L2BasePacket
{
public:
L2GamePacket();
L2GamePacket( const unsigned char *bytes, unsigned int length );
//virtual ~L2GamePacket();
public:
// in Hellbound key must be 16-byte array
// key is changed after enc/dec procedure
bool decodeXOR( unsigned char *key );
// in Hellbound key must be 16-byte array
// key is changed after enc/dec procedure
bool encodeXOR( unsigned char *key );
public:
static bool decodeXOR_buffer( unsigned char *decodeBytes, unsigned int bytesLen, unsigned char *key );
static bool encodeXOR_buffer( unsigned char *encodeBytes, unsigned int bytesLen, unsigned char *key );
};
#endif /*L2GAMEPACKET_H_*/

View File

@@ -0,0 +1,63 @@
#include "stdafx.h"
#include "L2Game_Action.h"
/* L2J:
private int _objectId;
@SuppressWarnings("unused")
private int _originX;
@SuppressWarnings("unused")
private int _originY;
@SuppressWarnings("unused")
private int _originZ;
private int _actionId;
@Override
protected void readImpl()
{
_objectId = readD(); // Target object Identifier
_originX = readD();
_originY = readD();
_originZ = readD();
_actionId = readC(); // Action identifier : 0-Simple click, 1-Shift click
}
*/
L2Game_Action::L2Game_Action()
{
this->_initNull();
}
L2Game_Action::L2Game_Action( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_Action::create( unsigned int objectID,
unsigned int originX,
unsigned int originY,
unsigned int originZ,
unsigned char bUseShift )
{
this->writeReset();
this->writeUChar( 0x1f ); // packet type - Action
this->writeUInt( objectID );
this->writeUInt( originX );
this->writeUInt( originY );
this->writeUInt( originZ );
this->writeUChar( bUseShift );
return true;
}
unsigned int L2Game_Action::read_objectID()
{
if( !(this->canReadBytes(5)) ) return 0;
this->readReset();
this->readUChar(); // pcode
return this->readUInt();
}
int L2Game_Action::read_originX() { return this->readInt(); }
int L2Game_Action::read_originY() { return this->readInt(); }
int L2Game_Action::read_originZ() { return this->readInt(); }
char L2Game_Action::read_useShift() { return this->readChar(); }

View File

@@ -0,0 +1,24 @@
#ifndef L2GAME_ACTION_H_
#define L2GAME_ACTION_H_
#include "../L2GamePacket.h"
class L2Game_Action : public L2GamePacket
{
public:
L2Game_Action();
L2Game_Action( const unsigned char *bytes, unsigned int length );
public:
bool create( unsigned int objectID,
unsigned int originX,
unsigned int originY,
unsigned int originZ,
unsigned char bUseShift );
unsigned int read_objectID();
int read_originX();
int read_originY();
int read_originZ();
char read_useShift();
};
#endif /*L2GAME_CHARACTERSELECT_H_*/

View File

@@ -0,0 +1,96 @@
#include "stdafx.h"
#include "L2Game_AuthLogin.h"
/* interlude pcode is 08
hellbound pcode is 2b
L2J:
protected void readImpl()
{
_loginName = readS().toLowerCase();
_playKey2 = readD();
_playKey1 = readD();
_loginKey1 = readD();
_loginKey2 = readD();
}
*/
L2Game_AuthLogin::L2Game_AuthLogin()
{
this->_initNull();
}
L2Game_AuthLogin::L2Game_AuthLogin( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
// session keys must point to 8-byte arrays
bool L2Game_AuthLogin::create( char *loginName,
unsigned char *sessionKey1,
unsigned char *sessionKey2 )
{
if( !loginName || !sessionKey1 || !sessionKey2 ) return false;
wchar_t loginU[32];
memset( loginU, 0, sizeof(loginU) );
#ifdef L2PACKETS_WINDOWS
_snwprintf( loginU, 32, L"%S", loginName );
#endif
#ifdef L2PACKETS_LINUX
swprintf( loginU, 32, L"%ls", loginName );
#endif
loginU[31] = 0;
return this->create( loginU, sessionKey1, sessionKey2 );
}
bool L2Game_AuthLogin::create( wchar_t *loginName,
unsigned char *sessionKey1,
unsigned char *sessionKey2 )
{
if( !loginName || !sessionKey1 || !sessionKey2 ) return false;
this->writeReset();
// write packet code
//this->writeUChar( 0x08 ); // interlude
this->writeUChar( 0x2b ); // hellbound
this->writeUnicodeString( loginName );
this->writeBytes( sessionKey2+4, 4 );
this->writeBytes( sessionKey2, 4 );
this->writeBytes( sessionKey1, 8 );
this->writeUInt( 1 );
return true;
}
bool L2Game_AuthLogin::read_login( wchar_t *loginOut )
{
if( !loginOut ) return false;
this->readReset();
this->readUChar();
loginOut[0] = 0;
wchar_t *login = this->readUnicodeString();
if( !login ) return false;
wcscpy( loginOut, login );
free( login );
return true;
}
bool L2Game_AuthLogin::read_login( char *loginOut )
{
if( !loginOut ) return false;
loginOut[0] = 0;
wchar_t loginU[32] = {0};
if( this->read_login(loginU) )
{
if( loginU[0] == 0 ) return true;
#ifdef L2PACKETS_WINDOWS
sprintf( loginOut, "%S", loginU );
#else
#ifdef L2PACKETS_LINUX
sprintf( loginOut, "%ls", loginU );
#else
#error Unknown OS? O_o
#endif
#endif
return true;
}
return false;
}

View File

@@ -0,0 +1,27 @@
#ifndef L2GAME_AUTHLOGIN_H_
#define L2GAME_AUTHLOGIN_H_
#include "../L2GamePacket.h"
class L2Game_AuthLogin : public L2GamePacket
{
public:
L2Game_AuthLogin();
L2Game_AuthLogin( const unsigned char *bytes, unsigned int length );
public:
// session keys must point to 8-byte arrays
bool create( char *loginName,
unsigned char *sessionKey1,
unsigned char *sessionKey2 );
// unicode version of upper function
// session keys must point to 8-byte arrays
bool create( wchar_t *loginName,
unsigned char *sessionKey1,
unsigned char *sessionKey2 );
public:
bool read_login( char *loginOut );
bool read_login( wchar_t *loginOut );
//bool read_session_keys( unsigned char *skey1, unsigned char *skey2 );
};
#endif /*L2GAME_AUTHLOGIN_H_*/

View File

@@ -0,0 +1,53 @@
#include "stdafx.h"
#include "L2Game_CharacterCreate.h"
/*
Client: Len 63 [CharacterCreate]
3F 00
0C // opcode
41 00 65 00 72 00 69 00 6E 00 00 00 // name
01 00 00 00 // race
01 00 00 00 // sex
19 00 00 00 // class id
1C 00 00 00 // INT
27 00 00 00 // STR
1E 00 00 00 // CON
1B 00 00 00 // MEN
23 00 00 00 // DEX
0B 00 00 00 // WIT
00 00 00 00 // hair style
00 00 00 00 // hair color
00 00 00 00 // face
*/
L2Game_CharacterCreate::L2Game_CharacterCreate()
{
_initNull();
}
L2Game_CharacterCreate::L2Game_CharacterCreate( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharacterCreate::create( const L2Game_NewCharacterTemplate *tmpl, const wchar_t *name,
int hairStyle, int hairColor, int face, int gender )
{
if( !tmpl ) return false;
setPacketType( 0x0C ); // CharacterCreate
writeS( name );
writeD( tmpl->race );
writeD( gender );
writeD( tmpl->classID );
writeD( tmpl->base_INT );
writeD( tmpl->base_STR );
writeD( tmpl->base_CON );
writeD( tmpl->base_MEN );
writeD( tmpl->base_DEX );
writeD( tmpl->base_WIT );
writeD( hairStyle );
writeD( hairColor );
writeD( face );
return true;
}

View File

@@ -0,0 +1,17 @@
#ifndef H_L2GAME_CHARACTERCREATE
#define H_L2GAME_CHARACTERCREATE
#include "../L2GamePacket.h"
#include "../server/L2Game_NewCharacterSuccess.h"
class L2Game_CharacterCreate: public L2GamePacket
{
public:
L2Game_CharacterCreate();
L2Game_CharacterCreate( const unsigned char *bytes, unsigned int length );
public:
bool create( const L2Game_NewCharacterTemplate *tmpl, const wchar_t *name,
int hairStyle, int hairColor, int face, int gender );
};
#endif

View File

@@ -0,0 +1,29 @@
#include "stdafx.h"
#include "L2Game_CharacterDelete.h"
L2Game_CharacterDelete::L2Game_CharacterDelete()
{
_initNull();
}
L2Game_CharacterDelete::L2Game_CharacterDelete( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharacterDelete::create( L2_VERSION ver )
{
ver = L2_VERSION_T1;
setPacketType( 0x0D ); // CharacterDelete
writeD( p_charSlot );
return true;
}
bool L2Game_CharacterDelete::parse( L2_VERSION ver )
{
ver = L2_VERSION_T1;
if( getPacketType() != 0x0D ) return false;
p_charSlot = readD();
return true;
}

View File

@@ -0,0 +1,18 @@
#ifndef H_L2GAME_CHARACTERDELETE
#define H_L2GAME_CHARACTERDELETE
#include "../L2GamePacket.h"
class L2Game_CharacterDelete: public L2GamePacket
{
public:
L2Game_CharacterDelete();
L2Game_CharacterDelete( const unsigned char *bytes, unsigned int length );
public:
bool create( L2_VERSION ver = L2_VERSION_T1 );
bool parse( L2_VERSION ver = L2_VERSION_T1 );
public:
int p_charSlot;
};
#endif

View File

@@ -0,0 +1,30 @@
#include "stdafx.h"
#include "L2Game_CharacterRestore.h"
L2Game_CharacterRestore::L2Game_CharacterRestore()
{
_initNull();
}
L2Game_CharacterRestore::L2Game_CharacterRestore( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharacterRestore::create( L2_VERSION ver )
{
ver = L2_VERSION_T1;
setPacketType( 0x7B ); // CharacterDelete
writeD( p_charSlot );
return true;
}
bool L2Game_CharacterRestore::parse( L2_VERSION ver )
{
ver = L2_VERSION_T1;
if( getPacketType() != 0x7B ) return false;
p_charSlot = readD();
return true;
}

View File

@@ -0,0 +1,18 @@
#ifndef H_L2GAME_CHARACTERRESTORE
#define H_L2GAME_CHARACTERRESTORE
#include "../L2GamePacket.h"
class L2Game_CharacterRestore: public L2GamePacket
{
public:
L2Game_CharacterRestore();
L2Game_CharacterRestore( const unsigned char *bytes, unsigned int length );
public:
bool create( L2_VERSION ver = L2_VERSION_T1 );
bool parse( L2_VERSION ver = L2_VERSION_T1 );
public:
int p_charSlot;
};
#endif

View File

@@ -0,0 +1,46 @@
#include "stdafx.h"
#include "L2Game_CharacterSelect.h"
/* L2J:
protected void readImpl()
{
_charSlot = readD();
_unk1 = readH();
_unk2 = readD();
_unk3 = readD();
_unk4 = readD();
}
*/
L2Game_CharacterSelect::L2Game_CharacterSelect()
{
this->_initNull();
}
L2Game_CharacterSelect::L2Game_CharacterSelect( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_CharacterSelect::create( unsigned int charSlot )
{
this->writeReset();
this->writeUChar( 0x12 ); // packet type
this->writeUInt( charSlot );
this->writeUShort( 0x0000 );
this->writeUInt( 0x00000000 );
this->writeUInt( 0x00000000 );
this->writeUInt( 0x00000000 );
return true;
}
bool L2Game_CharacterSelect::read_charSlot( unsigned int *charSlot )
{
if( !charSlot || !(this->canReadBytes(5)) ) return false;
(*charSlot) = 0;
this->readReset();
this->readUChar(); // pcode
(*charSlot) = this->readUInt();
return true;
}

View File

@@ -0,0 +1,16 @@
#ifndef L2GAME_CHARACTERSELECT_H_
#define L2GAME_CHARACTERSELECT_H_
#include "../L2GamePacket.h"
class L2Game_CharacterSelect : public L2GamePacket
{
public:
L2Game_CharacterSelect();
L2Game_CharacterSelect( const unsigned char *bytes, unsigned int length );
public:
bool create( unsigned int charSlot );
bool read_charSlot( unsigned int *charSlot );
};
#endif /*L2GAME_CHARACTERSELECT_H_*/

View File

@@ -0,0 +1,54 @@
#include "stdafx.h"
#include "L2Game_EnterWorld.h"
/*
Client: Len 107
6B 00
11
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C9 BC F2 A7 66 5A 0B 98 36 A5 BD 89 ED 7F E4 D7
6B 49 E2 9F EF 76 EB CE A3 FA F4 BF 0C 64 A3 B4
A4 CE DC C6 08 3E 6E EA 45 CA D3 FE 88 13 87 B8
06 2C 96 F0 9B 1E 8E BC C6 9B 98 C8 63 16 CF D0
29 00 00 00 0A E1 74 17 0A 08 00 08 5C 32 BD E1
5C 32 BE 22 5E 19 03 41
last 2 D's are different, depend on char
unsigned char array = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC9, 0xBC, 0xF2, 0xA7, 0x66, 0x5A, 0x0B, 0x98, 0x36, 0xA5, 0xBD, 0x89, 0xED, 0x7F, 0xE4, 0xD7,
0x6B, 0x49, 0xE2, 0x9F, 0xEF, 0x76, 0xEB, 0xCE, 0xA3, 0xFA, 0xF4, 0xBF, 0x0C, 0x64, 0xA3, 0xB4,
0xA4, 0xCE, 0xDC, 0xC6, 0x08, 0x3E, 0x6E, 0xEA, 0x45, 0xCA, 0xD3, 0xFE, 0x88, 0x13, 0x87, 0xB8,
0x06, 0x2C, 0x96, 0xF0, 0x9B, 0x1E, 0x8E, 0xBC, 0xC6, 0x9B, 0x98, 0xC8, 0x63, 0x16, 0xCF, 0xD0,
0x29, 0x00, 0x00, 0x00, 0x0A, 0xE1, 0x74, 0x17, 0x0A, 0x08, 0x00, 0x08, 0x5C, 0x32, 0xBD, 0xE1,
0x5C, 0x32, 0xBE, 0x22, 0x5E, 0x19, 0x03, 0x41, };
*/
L2Game_EnterWorld::L2Game_EnterWorld()
{
_initNull();
}
L2Game_EnterWorld::L2Game_EnterWorld( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_EnterWorld::create( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
unsigned char ew_array[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC9, 0xBC, 0xF2, 0xA7, 0x66, 0x5A, 0x0B, 0x98, 0x36, 0xA5, 0xBD, 0x89, 0xED, 0x7F, 0xE4, 0xD7,
0x6B, 0x49, 0xE2, 0x9F, 0xEF, 0x76, 0xEB, 0xCE, 0xA3, 0xFA, 0xF4, 0xBF, 0x0C, 0x64, 0xA3, 0xB4,
0xA4, 0xCE, 0xDC, 0xC6, 0x08, 0x3E, 0x6E, 0xEA, 0x45, 0xCA, 0xD3, 0xFE, 0x88, 0x13, 0x87, 0xB8,
0x06, 0x2C, 0x96, 0xF0, 0x9B, 0x1E, 0x8E, 0xBC, 0xC6, 0x9B, 0x98, 0xC8, 0x63, 0x16, 0xCF, 0xD0,
0x29, 0x00, 0x00, 0x00, 0x0A, 0xE1, 0x74, 0x17, 0x0A, 0x08, 0x00, 0x08, 0x5C, 0x32, 0xBD, 0xE1,
0x5C, 0x32, 0xBE, 0x22, 0x5E, 0x19, 0x03, 0x41 };
this->writeReset();
this->writeUChar( 0x11 ); // EnterWorld
this->writeBytes( ew_array, sizeof(ew_array) );
return true;
}

View File

@@ -0,0 +1,16 @@
#ifndef L2GAME_ENTERWORLD_H_
#define L2GAME_ENTERWORLD_H_
#include "../L2GamePacket.h"
class L2Game_EnterWorld : public L2GamePacket
{
public:
L2Game_EnterWorld();
L2Game_EnterWorld( const unsigned char *bytes, unsigned int length );
public:
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
//void read() {} // L2J Server ignores its contents, parsing is unknown :)
};
#endif

View File

@@ -0,0 +1,33 @@
#include "stdafx.h"
#include "L2Game_NewCharacter.h"
/**
Client: Len 3 [NewCharacter]
03 00
13 // opcode
*/
L2Game_NewCharacter::L2Game_NewCharacter()
{
_initNull();
}
L2Game_NewCharacter::L2Game_NewCharacter( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_NewCharacter::create( L2_VERSION ver )
{
ver = L2_VERSION_T1;
setPacketType( 0x13 );
return true;
}
bool L2Game_NewCharacter::parse( L2_VERSION ver )
{
ver = L2_VERSION_T1;
// just trugger
return true;
}

View File

@@ -0,0 +1,16 @@
#ifndef H_L2GAME_NEWCHARACTER
#define H_L2GAME_NEWCHARACTER
#include "../L2GamePacket.h"
class L2Game_NewCharacter: public L2GamePacket
{
public:
L2Game_NewCharacter();
L2Game_NewCharacter( const unsigned char *bytes, unsigned int length );
public:
bool create( L2_VERSION ver = L2_VERSION_T1 );
bool parse( L2_VERSION ver = L2_VERSION_T1 );
};
#endif

View File

@@ -0,0 +1,274 @@
#include "stdafx.h"
#include "L2Game_ProtocolVersion.h"
/* L2J:
// "[C] 00 ProtocolVersion";
* pcode 0c00 is in interlude
* pcode 0x0e is in hellbound
protected void readImpl()
{
_version = readD();
}
*/
L2Game_ProtocolVersion::L2Game_ProtocolVersion()
{
this->_initNull();
}
L2Game_ProtocolVersion::L2Game_ProtocolVersion( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_ProtocolVersion::create( L2_VERSION ver )
{
switch( ver )
{
case L2_VERSION_T1: this->createDefaultKamael(); break;
case L2_VERSION_T15: this->createDefaultHellbound(); break;
case L2_VERSION_T2: this->createDefaultGracia1(); break;
case L2_VERSION_T22: this->createDefaultGracia2(); break;
case L2_VERSION_T23: this->createDefaultGracia3(); break;
case L2_VERSION_T24: this->createDefaultGracia4(); break;
default: return false; break;
}
return true;
}
/** Kamael
C->S
0B 01 // len
0E // p.code ProtocolVersion
3C 03 00 00 // protocol - 828
09 07 54 56 03 09 0B 01 07 02 54 54 56 07 00 02
55 56 00 51 00 53 57 04 07 55 08 54 01 07 01 53
00 56 55 56 01 06 05 04 51 03 08 51 08 51 56 04
54 06 55 08 02 09 51 56 01 53 06 55 04 53 00 56
56 53 01 09 02 09 01 51 54 51 09 55 56 09 03 04
07 05 55 04 06 55 04 06 09 04 51 01 08 08 06 05
52 06 04 01 07 54 03 06 52 55 06 55 55 51 01 02
04 54 03 55 54 01 57 51 55 05 52 05 54 07 51 51
55 07 02 53 53 00 52 05 52 07 01 54 00 03 05 05
08 06 05 05 06 03 00 0D 08 01 07 09 03 51 03 07
53 09 51 06 07 54 0A 50 56 02 52 04 05 55 51 02
53 00 08 54 04 52 56 06 02 09 00 08 03 53 56 01
05 00 55 06 08 56 04 0D 06 07 52 06 07 04 0A 06
01 04 54 04 00 05 02 04 54 00 09 52 53 05 04 01
04 05 05 01 52 51 52 0D 06 51 08 09 54 53 00 0D
01 02 03 54 53 01 05 03 08 56 54 07 02 54 0B 06
8D 71 5F 08
*/
bool L2Game_ProtocolVersion::createDefaultKamael( unsigned int gameProtoVer /*= 828*/ )
{
this->writeReset();
// packet code 0x00 was in Interlude!!!!
// this->writeUChar( 0x00 ); // packet type - ProtocolVersion
// in Hellbound this code is 0x0e
this->writeUChar( 0x0e ); // packet type - ProtocolVersion
this->writeUInt( gameProtoVer );
unsigned char pv_array[] = {
0x09, 0x07, 0x54, 0x56, 0x03, 0x09, 0x0B, 0x01, 0x07, 0x02, 0x54, 0x54, 0x56, 0x07, 0x00, 0x02,
0x55, 0x56, 0x00, 0x51, 0x00, 0x53, 0x57, 0x04, 0x07, 0x55, 0x08, 0x54, 0x01, 0x07, 0x01, 0x53,
0x00, 0x56, 0x55, 0x56, 0x01, 0x06, 0x05, 0x04, 0x51, 0x03, 0x08, 0x51, 0x08, 0x51, 0x56, 0x04,
0x54, 0x06, 0x55, 0x08, 0x02, 0x09, 0x51, 0x56, 0x01, 0x53, 0x06, 0x55, 0x04, 0x53, 0x00, 0x56,
0x56, 0x53, 0x01, 0x09, 0x02, 0x09, 0x01, 0x51, 0x54, 0x51, 0x09, 0x55, 0x56, 0x09, 0x03, 0x04,
0x07, 0x05, 0x55, 0x04, 0x06, 0x55, 0x04, 0x06, 0x09, 0x04, 0x51, 0x01, 0x08, 0x08, 0x06, 0x05,
0x52, 0x06, 0x04, 0x01, 0x07, 0x54, 0x03, 0x06, 0x52, 0x55, 0x06, 0x55, 0x55, 0x51, 0x01, 0x02,
0x04, 0x54, 0x03, 0x55, 0x54, 0x01, 0x57, 0x51, 0x55, 0x05, 0x52, 0x05, 0x54, 0x07, 0x51, 0x51,
0x55, 0x07, 0x02, 0x53, 0x53, 0x00, 0x52, 0x05, 0x52, 0x07, 0x01, 0x54, 0x00, 0x03, 0x05, 0x05,
0x08, 0x06, 0x05, 0x05, 0x06, 0x03, 0x00, 0x0D, 0x08, 0x01, 0x07, 0x09, 0x03, 0x51, 0x03, 0x07,
0x53, 0x09, 0x51, 0x06, 0x07, 0x54, 0x0A, 0x50, 0x56, 0x02, 0x52, 0x04, 0x05, 0x55, 0x51, 0x02,
0x53, 0x00, 0x08, 0x54, 0x04, 0x52, 0x56, 0x06, 0x02, 0x09, 0x00, 0x08, 0x03, 0x53, 0x56, 0x01,
0x05, 0x00, 0x55, 0x06, 0x08, 0x56, 0x04, 0x0D, 0x06, 0x07, 0x52, 0x06, 0x07, 0x04, 0x0A, 0x06,
0x01, 0x04, 0x54, 0x04, 0x00, 0x05, 0x02, 0x04, 0x54, 0x00, 0x09, 0x52, 0x53, 0x05, 0x04, 0x01,
0x04, 0x05, 0x05, 0x01, 0x52, 0x51, 0x52, 0x0D, 0x06, 0x51, 0x08, 0x09, 0x54, 0x53, 0x00, 0x0D,
0x01, 0x02, 0x03, 0x54, 0x53, 0x01, 0x05, 0x03, 0x08, 0x56, 0x54, 0x07, 0x02, 0x54, 0x0B, 0x06,
0x8D, 0x71, 0x5F, 0x08 };
writeBytes( pv_array, sizeof(pv_array) );
return true;
}
/* Hellbound
C->S Len 267
0B 01 // len
0E // p. code
3F 03 00 00 // protocol - 831 (Hellbound?)
09 07 54 56 03 09 0B 01 07 02 54 54 56 07 00 02
55 56 00 51 00 53 57 04 07 55 08 54 01 07 01 53
00 56 55 56 01 06 05 04 51 03 08 51 08 51 56 04
54 06 55 08 02 09 51 56 01 53 06 55 04 53 00 56
56 53 01 09 02 09 01 51 54 51 09 55 56 09 03 04
07 05 55 04 06 55 04 06 09 04 51 01 08 08 06 05
52 06 04 01 07 54 03 06 52 55 06 55 55 51 01 02
04 54 03 55 54 01 57 51 55 05 52 05 54 07 51 51
55 07 02 53 53 00 52 05 52 07 01 54 00 03 05 05
08 06 05 05 06 03 00 0D 08 01 07 09 03 51 03 07
53 09 51 06 07 54 0A 50 56 02 52 04 05 55 51 02
53 00 08 54 04 52 56 06 02 09 00 08 03 53 56 01
05 00 55 06 08 56 04 0D 06 07 52 06 07 04 0A 06
01 04 54 04 00 05 02 04 54 00 09 52 53 05 04 01
04 05 05 01 52 51 52 0D 06 51 08 09 54 53 00 0D
01 02 03 54 53 01 05 03 08 56 54 07 02 54 0B 06
FB 87 B9 4A
*/
bool L2Game_ProtocolVersion::createDefaultHellbound( unsigned int gameProtoVer /*= 851*/ )
{
this->writeReset();
// packet code 0x00 was in Interlude!!!!
// this->writeUChar( 0x00 ); // packet type - ProtocolVersion
// in Hellbound this code is 0x0e
this->writeUChar( 0x0e ); // packet type - ProtocolVersion
this->writeUInt( gameProtoVer );
unsigned char pv_array[] = {
0x09, 0x07, 0x54, 0x56, 0x03, 0x09, 0x0B, 0x01, 0x07, 0x02, 0x54, 0x54, 0x56, 0x07, 0x00, 0x02,
0x55, 0x56, 0x00, 0x51, 0x00, 0x53, 0x57, 0x04, 0x07, 0x55, 0x08, 0x54, 0x01, 0x07, 0x01, 0x53,
0x00, 0x56, 0x55, 0x56, 0x01, 0x06, 0x05, 0x04, 0x51, 0x03, 0x08, 0x51, 0x08, 0x51, 0x56, 0x04,
0x54, 0x06, 0x55, 0x08, 0x02, 0x09, 0x51, 0x56, 0x01, 0x53, 0x06, 0x55, 0x04, 0x53, 0x00, 0x56,
0x56, 0x53, 0x01, 0x09, 0x02, 0x09, 0x01, 0x51, 0x54, 0x51, 0x09, 0x55, 0x56, 0x09, 0x03, 0x04,
0x07, 0x05, 0x55, 0x04, 0x06, 0x55, 0x04, 0x06, 0x09, 0x04, 0x51, 0x01, 0x08, 0x08, 0x06, 0x05,
0x52, 0x06, 0x04, 0x01, 0x07, 0x54, 0x03, 0x06, 0x52, 0x55, 0x06, 0x55, 0x55, 0x51, 0x01, 0x02,
0x04, 0x54, 0x03, 0x55, 0x54, 0x01, 0x57, 0x51, 0x55, 0x05, 0x52, 0x05, 0x54, 0x07, 0x51, 0x51,
0x55, 0x07, 0x02, 0x53, 0x53, 0x00, 0x52, 0x05, 0x52, 0x07, 0x01, 0x54, 0x00, 0x03, 0x05, 0x05,
0x08, 0x06, 0x05, 0x05, 0x06, 0x03, 0x00, 0x0D, 0x08, 0x01, 0x07, 0x09, 0x03, 0x51, 0x03, 0x07,
0x53, 0x09, 0x51, 0x06, 0x07, 0x54, 0x0A, 0x50, 0x56, 0x02, 0x52, 0x04, 0x05, 0x55, 0x51, 0x02,
0x53, 0x00, 0x08, 0x54, 0x04, 0x52, 0x56, 0x06, 0x02, 0x09, 0x00, 0x08, 0x03, 0x53, 0x56, 0x01,
0x05, 0x00, 0x55, 0x06, 0x08, 0x56, 0x04, 0x0D, 0x06, 0x07, 0x52, 0x06, 0x07, 0x04, 0x0A, 0x06,
0x01, 0x04, 0x54, 0x04, 0x00, 0x05, 0x02, 0x04, 0x54, 0x00, 0x09, 0x52, 0x53, 0x05, 0x04, 0x01,
0x04, 0x05, 0x05, 0x01, 0x52, 0x51, 0x52, 0x0D, 0x06, 0x51, 0x08, 0x09, 0x54, 0x53, 0x00, 0x0D,
0x01, 0x02, 0x03, 0x54, 0x53, 0x01, 0x05, 0x03, 0x08, 0x56, 0x54, 0x07, 0x02, 0x54, 0x0B, 0x06,
0xFB, 0x87, 0xB9, 0x4A };
writeBytes( pv_array, sizeof(pv_array) );
return true;
}
bool L2Game_ProtocolVersion::createDefaultGracia1( unsigned int gameProtoVer /*= 12*/ )
{
this->writeReset();
// packet code 0x00 was in Interlude!!!!
// this->writeUChar( 0x00 ); // packet type - ProtocolVersion
// in Hellbound this code is 0x0e
this->writeUChar( 0x0e ); // packet type - ProtocolVersion
this->writeUInt( gameProtoVer );
unsigned char pv_array[] = {
0x09, 0x07, 0x54, 0x56, 0x03, 0x09, 0x0b, 0x01, 0x07, 0x02, 0x54, 0x54, 0x56, 0x07, 0x00, 0x02,
0x55, 0x56, 0x00, 0x51, 0x00, 0x53, 0x57, 0x04, 0x07, 0x55, 0x08, 0x54, 0x01, 0x07, 0x01, 0x53,
0x00, 0x56, 0x55, 0x56, 0x01, 0x06, 0x05, 0x04, 0x51, 0x03, 0x08, 0x51, 0x08, 0x51, 0x56, 0x04,
0x54, 0x06, 0x55, 0x08, 0x02, 0x09, 0x51, 0x56, 0x01, 0x53, 0x06, 0x55, 0x04, 0x53, 0x00, 0x56,
0x56, 0x53, 0x01, 0x09, 0x02, 0x09, 0x01, 0x51, 0x54, 0x51, 0x09, 0x55, 0x56, 0x09, 0x03, 0x04,
0x07, 0x05, 0x55, 0x04, 0x06, 0x55, 0x04, 0x06, 0x09, 0x04, 0x51, 0x01, 0x08, 0x08, 0x06, 0x05,
0x52, 0x06, 0x04, 0x01, 0x07, 0x54, 0x03, 0x06, 0x52, 0x55, 0x06, 0x55, 0x55, 0x51, 0x01, 0x02,
0x04, 0x54, 0x03, 0x55, 0x54, 0x01, 0x57, 0x51, 0x55, 0x05, 0x52, 0x05, 0x54, 0x07, 0x51, 0x51,
0x55, 0x07, 0x02, 0x53, 0x53, 0x00, 0x52, 0x05, 0x52, 0x07, 0x01, 0x54, 0x00, 0x03, 0x05, 0x05,
0x08, 0x06, 0x05, 0x05, 0x06, 0x03, 0x00, 0x0d, 0x08, 0x01, 0x07, 0x09, 0x03, 0x51, 0x03, 0x07,
0x53, 0x09, 0x51, 0x06, 0x07, 0x54, 0x0a, 0x50, 0x56, 0x02, 0x52, 0x04, 0x05, 0x55, 0x51, 0x02,
0x53, 0x00, 0x08, 0x54, 0x04, 0x52, 0x56, 0x06, 0x02, 0x09, 0x00, 0x08, 0x03, 0x53, 0x56, 0x01,
0x05, 0x00, 0x55, 0x06, 0x08, 0x56, 0x04, 0x0d, 0x06, 0x07, 0x52, 0x06, 0x07, 0x04, 0x0a, 0x06,
0x01, 0x04, 0x54, 0x04, 0x00, 0x05, 0x02, 0x04, 0x54, 0x00, 0x09, 0x52, 0x53, 0x05, 0x04, 0x01,
0x04, 0x05, 0x05, 0x01, 0x52, 0x51, 0x52, 0x0d, 0x06, 0x51, 0x08, 0x09, 0x54, 0x53, 0x00, 0x0d,
0x01, 0x02, 0x03, 0x54, 0x53, 0x01, 0x05, 0x03, 0x08, 0x56, 0x54, 0x07, 0x02, 0x54, 0x0b, 0x06,
0xdf, 0xb8, 0x3b, 0x54 };
writeBytes( pv_array, sizeof(pv_array) );
return true;
}
// TODO: validate
bool L2Game_ProtocolVersion::createDefaultGracia2( unsigned int gameProtoVer /*= 17*/ )
{
this->writeReset();
// packet code 0x00 was in Interlude!!!!
// this->writeUChar( 0x00 ); // packet type - ProtocolVersion
// in Hellbound this code is 0x0e
this->writeUChar( 0x0e ); // packet type - ProtocolVersion
this->writeUInt( gameProtoVer );
unsigned char pv_array[] = {
0x09, 0x07, 0x54, 0x56, 0x03, 0x09, 0x0B, 0x01, 0x07, 0x02, 0x54, 0x54, 0x56, 0x07, 0x00, 0x02,
0x55, 0x56, 0x00, 0x51, 0x00, 0x53, 0x57, 0x04, 0x07, 0x55, 0x08, 0x54, 0x01, 0x07, 0x01, 0x53,
0x00, 0x56, 0x55, 0x56, 0x01, 0x06, 0x05, 0x04, 0x51, 0x03, 0x08, 0x51, 0x08, 0x51, 0x56, 0x04,
0x54, 0x06, 0x55, 0x08, 0x02, 0x09, 0x51, 0x56, 0x01, 0x53, 0x06, 0x55, 0x04, 0x53, 0x00, 0x56,
0x56, 0x53, 0x01, 0x09, 0x02, 0x09, 0x01, 0x51, 0x54, 0x51, 0x09, 0x55, 0x56, 0x09, 0x03, 0x04,
0x07, 0x05, 0x55, 0x04, 0x06, 0x55, 0x04, 0x06, 0x09, 0x04, 0x51, 0x01, 0x08, 0x08, 0x06, 0x05,
0x52, 0x06, 0x04, 0x01, 0x07, 0x54, 0x03, 0x06, 0x52, 0x55, 0x06, 0x55, 0x55, 0x51, 0x01, 0x02,
0x04, 0x54, 0x03, 0x55, 0x54, 0x01, 0x57, 0x51, 0x55, 0x05, 0x52, 0x05, 0x54, 0x07, 0x51, 0x51,
0x55, 0x07, 0x02, 0x53, 0x53, 0x00, 0x52, 0x05, 0x52, 0x07, 0x01, 0x54, 0x00, 0x03, 0x05, 0x05,
0x08, 0x06, 0x05, 0x05, 0x06, 0x03, 0x00, 0x0D, 0x08, 0x01, 0x07, 0x09, 0x03, 0x51, 0x03, 0x07,
0x53, 0x09, 0x51, 0x06, 0x07, 0x54, 0x0A, 0x50, 0x56, 0x02, 0x52, 0x04, 0x05, 0x55, 0x51, 0x02,
0x53, 0x00, 0x08, 0x54, 0x04, 0x52, 0x56, 0x06, 0x02, 0x09, 0x00, 0x08, 0x03, 0x53, 0x56, 0x01,
0x05, 0x00, 0x55, 0x06, 0x08, 0x56, 0x04, 0x0D, 0x06, 0x07, 0x52, 0x06, 0x07, 0x04, 0x0A, 0x06,
0x01, 0x04, 0x54, 0x04, 0x00, 0x05, 0x02, 0x04, 0x54, 0x00, 0x09, 0x52, 0x53, 0x05, 0x04, 0x01,
0x04, 0x05, 0x05, 0x01, 0x52, 0x51, 0x52, 0x0D, 0x06, 0x51, 0x08, 0x09, 0x54, 0x53, 0x00, 0x0D,
0x01, 0x02, 0x03, 0x54, 0x53, 0x01, 0x05, 0x03, 0x08, 0x56, 0x54, 0x07, 0x02, 0x54, 0x0B, 0x06,
0xEB, 0xEF, 0x3D, 0xE6 };
writeBytes( pv_array, sizeof(pv_array) );
return true;
}
bool L2Game_ProtocolVersion::createDefaultGracia3( unsigned int gameProtoVer /*= 83*/ )
{
this->writeReset();
// packet code 0x00 was in Interlude!!!!
// this->writeUChar( 0x00 ); // packet type - ProtocolVersion
// in Hellbound this code is 0x0e
this->writeUChar( 0x0e ); // packet type - ProtocolVersion
this->writeUInt( gameProtoVer );
unsigned char pv_array[] = {
0x09, 0x07, 0x54, 0x56, 0x03, 0x09, 0x0B, 0x01, 0x07, 0x02, 0x54, 0x54, 0x56, 0x07, 0x00, 0x02,
0x55, 0x56, 0x00, 0x51, 0x00, 0x53, 0x57, 0x04, 0x07, 0x55, 0x08, 0x54, 0x01, 0x07, 0x01, 0x53,
0x00, 0x56, 0x55, 0x56, 0x01, 0x06, 0x05, 0x04, 0x51, 0x03, 0x08, 0x51, 0x08, 0x51, 0x56, 0x04,
0x54, 0x06, 0x55, 0x08, 0x02, 0x09, 0x51, 0x56, 0x01, 0x53, 0x06, 0x55, 0x04, 0x53, 0x00, 0x56,
0x56, 0x53, 0x01, 0x09, 0x02, 0x09, 0x01, 0x51, 0x54, 0x51, 0x09, 0x55, 0x56, 0x09, 0x03, 0x04,
0x07, 0x05, 0x55, 0x04, 0x06, 0x55, 0x04, 0x06, 0x09, 0x04, 0x51, 0x01, 0x08, 0x08, 0x06, 0x05,
0x52, 0x06, 0x04, 0x01, 0x07, 0x54, 0x03, 0x06, 0x52, 0x55, 0x06, 0x55, 0x55, 0x51, 0x01, 0x02,
0x04, 0x54, 0x03, 0x55, 0x54, 0x01, 0x57, 0x51, 0x55, 0x05, 0x52, 0x05, 0x54, 0x07, 0x51, 0x51,
0x55, 0x07, 0x02, 0x53, 0x53, 0x00, 0x52, 0x05, 0x52, 0x07, 0x01, 0x54, 0x00, 0x03, 0x05, 0x05,
0x08, 0x06, 0x05, 0x05, 0x06, 0x03, 0x00, 0x0D, 0x08, 0x01, 0x07, 0x09, 0x03, 0x51, 0x03, 0x07,
0x53, 0x09, 0x51, 0x06, 0x07, 0x54, 0x0A, 0x50, 0x56, 0x02, 0x52, 0x04, 0x05, 0x55, 0x51, 0x02,
0x53, 0x00, 0x08, 0x54, 0x04, 0x52, 0x56, 0x06, 0x02, 0x09, 0x00, 0x08, 0x03, 0x53, 0x56, 0x01,
0x05, 0x00, 0x55, 0x06, 0x08, 0x56, 0x04, 0x0D, 0x06, 0x07, 0x52, 0x06, 0x07, 0x04, 0x0A, 0x06,
0x01, 0x04, 0x54, 0x04, 0x00, 0x05, 0x02, 0x04, 0x54, 0x00, 0x09, 0x52, 0x53, 0x05, 0x04, 0x01,
0x04, 0x05, 0x05, 0x01, 0x52, 0x51, 0x52, 0x0D, 0x06, 0x51, 0x08, 0x09, 0x54, 0x53, 0x00, 0x0D,
0x01, 0x02, 0x03, 0x54, 0x53, 0x01, 0x05, 0x03, 0x08, 0x56, 0x54, 0x07, 0x02, 0x54, 0x0B, 0x06,
0x11, 0x5D, 0x1F, 0x60 }; // these last 4 bytes always differ :)
writeBytes( pv_array, sizeof(pv_array) );
return true;
}
bool L2Game_ProtocolVersion::createDefaultGracia4( unsigned int gameProtoVer /*= 146*/ )
{
this->writeReset();
this->writeUChar( 0x0e ); // packet type - ProtocolVersion
this->writeUInt( gameProtoVer );
unsigned char pv_array[] = {
0x09, 0x07, 0x54, 0x56, 0x03, 0x09, 0x0B, 0x01, 0x07, 0x02, 0x54, 0x54, 0x56, 0x07, 0x00, 0x02,
0x55, 0x56, 0x00, 0x51, 0x00, 0x53, 0x57, 0x04, 0x07, 0x55, 0x08, 0x54, 0x01, 0x07, 0x01, 0x53,
0x00, 0x56, 0x55, 0x56, 0x01, 0x06, 0x05, 0x04, 0x51, 0x03, 0x08, 0x51, 0x08, 0x51, 0x56, 0x04,
0x54, 0x06, 0x55, 0x08, 0x02, 0x09, 0x51, 0x56, 0x01, 0x53, 0x06, 0x55, 0x04, 0x53, 0x00, 0x56,
0x56, 0x53, 0x01, 0x09, 0x02, 0x09, 0x01, 0x51, 0x54, 0x51, 0x09, 0x55, 0x56, 0x09, 0x03, 0x04,
0x07, 0x05, 0x55, 0x04, 0x06, 0x55, 0x04, 0x06, 0x09, 0x04, 0x51, 0x01, 0x08, 0x08, 0x06, 0x05,
0x52, 0x06, 0x04, 0x01, 0x07, 0x54, 0x03, 0x06, 0x52, 0x55, 0x06, 0x55, 0x55, 0x51, 0x01, 0x02,
0x04, 0x54, 0x03, 0x55, 0x54, 0x01, 0x57, 0x51, 0x55, 0x05, 0x52, 0x05, 0x54, 0x07, 0x51, 0x51,
0x55, 0x07, 0x02, 0x53, 0x53, 0x00, 0x52, 0x05, 0x52, 0x07, 0x01, 0x54, 0x00, 0x03, 0x05, 0x05,
0x08, 0x06, 0x05, 0x05, 0x06, 0x03, 0x00, 0x0D, 0x08, 0x01, 0x07, 0x09, 0x03, 0x51, 0x03, 0x07,
0x53, 0x09, 0x51, 0x06, 0x07, 0x54, 0x0A, 0x50, 0x56, 0x02, 0x52, 0x04, 0x05, 0x55, 0x51, 0x02,
0x53, 0x00, 0x08, 0x54, 0x04, 0x52, 0x56, 0x06, 0x02, 0x09, 0x00, 0x08, 0x03, 0x53, 0x56, 0x01,
0x05, 0x00, 0x55, 0x06, 0x08, 0x56, 0x04, 0x0D, 0x06, 0x07, 0x52, 0x06, 0x07, 0x04, 0x0A, 0x06,
0x01, 0x04, 0x54, 0x04, 0x00, 0x05, 0x02, 0x04, 0x54, 0x00, 0x09, 0x52, 0x53, 0x05, 0x04, 0x01,
0x04, 0x05, 0x05, 0x01, 0x52, 0x51, 0x52, 0x0D, 0x06, 0x51, 0x08, 0x09, 0x54, 0x53, 0x00, 0x0D,
0x01, 0x02, 0x03, 0x54, 0x53, 0x01, 0x05, 0x03, 0x08, 0x56, 0x54, 0x07, 0x02, 0x54, 0x0B, 0x06,
0xA6, 0x23, 0xF4, 0xFE }; // these last 4 bytes always differ :)
writeBytes( pv_array, sizeof(pv_array) );
return true;
}
bool L2Game_ProtocolVersion::read_protoVer( unsigned int *pver )
{
if( !pver || !(this->canReadBytes(5)) ) return false;
(*pver) = 0;
this->readReset();
this->readUChar();
(*pver) = this->readUInt();
return true;
}

View File

@@ -0,0 +1,22 @@
#ifndef L2GAME_PROTOCOLVERSION_H_
#define L2GAME_PROTOCOLVERSION_H_
#include "../L2GamePacket.h"
class L2Game_ProtocolVersion : public L2GamePacket
{
public:
L2Game_ProtocolVersion();
L2Game_ProtocolVersion( const unsigned char *bytes, unsigned int length );
public:
bool create( L2_VERSION ver = L2_VERSION_T1 );
bool createDefaultKamael( unsigned int gameProtoVer = 828 );
bool createDefaultHellbound( unsigned int gameProtoVer = 851 );
bool createDefaultGracia1( unsigned int gameProtoVer = 12 );
bool createDefaultGracia2( unsigned int gameProtoVer = 17 );
bool createDefaultGracia3( unsigned int gameProtoVer = 83 );
bool createDefaultGracia4( unsigned int gameProtoVer = 146 );
bool read_protoVer( unsigned int *pver );
};
#endif /*L2GAME_PROTOCOLVERSION_H_*/

View File

@@ -0,0 +1,30 @@
#include "stdafx.h"
#include "L2Game_RequestGotoLobby.h"
L2Game_RequestGotoLobby::L2Game_RequestGotoLobby()
{
this->_initNull();
}
L2Game_RequestGotoLobby::L2Game_RequestGotoLobby( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_RequestGotoLobby::create( L2_VERSION ver )
{
if( ver <= L2_VERSION_T22 ) setPacketType2( 0xD0, 0x0039 );
if( ver >= L2_VERSION_T23 ) setPacketType2( 0xD0, 0x0036 );
return true;
}
bool L2Game_RequestGotoLobby::parse( L2_VERSION ver )
{
if( getPacketType() != 0xD0 ) return false;
if( ver <= L2_VERSION_T22 )
if( readUShort() != 0x0039 ) return false;
if( ver >= L2_VERSION_T23 )
if( readUShort() != 0x0036 ) return false;
return true;
}

View File

@@ -0,0 +1,16 @@
#ifndef L2GAME_REQEUSTGOTOLOBBY_H_
#define L2GAME_REQUESTGOTOLOBBY_H_
#include "../L2GamePacket.h"
class L2Game_RequestGotoLobby : public L2GamePacket
{
public:
L2Game_RequestGotoLobby();
L2Game_RequestGotoLobby( const unsigned char *bytes, unsigned int length );
public:
bool create( L2_VERSION ver = L2_VERSION_T1 );
bool parse( L2_VERSION ver = L2_VERSION_T1 );
};
#endif /*L2GAME_CHARACTERSELECT_H_*/

View File

@@ -0,0 +1,44 @@
#include "stdafx.h"
#include "L2Game_RequestJoinParty.h"
/* L2J:
Client: Len 15
0F 00
42
6C 00 6F 00 6C 00 00 00 // target char name
00 00 00 00 // loot type, item distribution
*/
L2Game_RequestJoinParty::L2Game_RequestJoinParty()
{
this->_initNull();
}
L2Game_RequestJoinParty::L2Game_RequestJoinParty( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_RequestJoinParty::create( const wchar_t *invitePlayer, unsigned int lootRule )
{
if( !invitePlayer ) return false;
writeReset();
writeUChar( 0x42 );
writeUnicodeString( invitePlayer );
writeUInt( lootRule );
return true;
}
bool L2Game_RequestJoinParty::read_invitePlayer( wchar_t *out )
{
if( !out ) return false;
readReset();
wcscpy( out, readUnicodeStringPtr() );
return true;
}
unsigned int L2Game_RequestJoinParty::read_lootRule()
{
return readUInt();
}

View File

@@ -0,0 +1,30 @@
#ifndef L2GAME_REQUESTJOINPARY_H_
#define L2GAME_REQUESTJOINPARY_H_
#include "../L2GamePacket.h"
#define L2_PARTY_LOOT_ITEM_LOOTER 0
#define L2_PARTY_LOOT_ITEM_RANDOM 1
#define L2_PARTY_LOOT_ITEM_RANDOM_SPOIL 2
#define L2_PARTY_LOOT_ITEM_ORDER 3
#define L2_PARTY_LOOT_ITEM_ORDER_SPOIL 4
class L2Game_RequestJoinParty: public L2GamePacket
{
public:
static const unsigned int ITEM_LOOTER = 0;
static const unsigned int ITEM_RANDOM = 1;
static const unsigned int ITEM_RANDOM_SPOIL = 2;
static const unsigned int ITEM_ORDER = 3;
static const unsigned int ITEM_ORDER_SPOIL = 4;
public:
L2Game_RequestJoinParty();
L2Game_RequestJoinParty( const unsigned char *bytes, unsigned int length );
public:
bool create( const wchar_t *invitePlayer, unsigned int lootRule );
public:
bool read_invitePlayer( wchar_t *out );
unsigned int read_lootRule();
};
#endif

View File

@@ -0,0 +1,56 @@
#include "stdafx.h"
#include "L2Game_RequestUserCommand.h"
/* L2J:
Client Len 7 [ RequestUserCommand]
07 00
B3
00 00 00 00 // command ID
================================
Decimal command numbers:
0 - /loc
52 - /unstuck (Escape)
61 - /Mount
62 - /DisMount
77 - /time
81 - /partyinfo
88 - /AttackList
89 - /underattacklist
90 - /warlist
93 - /ChannelDelete
96 - /ChannelLeave
97 - /ChannelListUpdate
100 - /ClanPenalty
109 - /OlympiadStat
114 - /InstanceZone
*/
L2Game_RequestUserCommand::L2Game_RequestUserCommand()
{
this->_initNull();
}
L2Game_RequestUserCommand::L2Game_RequestUserCommand( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_RequestUserCommand::create( unsigned int commandID )
{
writeReset();
writeUChar( 0xB3 );
writeUInt( commandID );
return true;
}
unsigned int L2Game_RequestUserCommand::read_commandID()
{
readReset();
getPacketType();
return readUInt();
}

View File

@@ -0,0 +1,33 @@
#ifndef L2GAME_REQUESTUSERCOMMAND_H_
#define L2GAME_REQUESTUSERCOMMAND_H_
#include "../L2GamePacket.h"
class L2Game_RequestUserCommand: public L2GamePacket
{
public:
static const unsigned int CMD_LOC = 0;
static const unsigned int CMD_UNSTUCK = 52;
static const unsigned int CMD_MOUNT = 61;
static const unsigned int CMD_DISMOUNT = 62;
static const unsigned int CMD_TIME = 77;
static const unsigned int CMD_PARTYINFO = 81;
static const unsigned int CMD_ATTACKLIST = 88;
static const unsigned int CMD_UNDERATTACKLIST = 89;
static const unsigned int CMD_WARLIST = 90;
static const unsigned int CMD_CHANNELDELETE = 93;
static const unsigned int CMD_CHANNELLEAVE = 96;
static const unsigned int CMD_CHANNELLISTUPDATE = 97;
static const unsigned int CMD_CLANPENALTY = 100;
static const unsigned int CMD_OLYMPIADSTAT = 109;
static const unsigned int CMD_INSTANCEZONE = 114;
public:
L2Game_RequestUserCommand();
L2Game_RequestUserCommand( const unsigned char *bytes, unsigned int length );
public:
bool create( unsigned int commandID );
public:
unsigned int read_commandID();
};
#endif

View File

@@ -0,0 +1,37 @@
#include "stdafx.h"
#include "L2Game_UseItem.h"
/*
0B 00 // len 11
19 // ptype - UseItem
57 EA 03 10 // objectID? 268692055
00 00 00 00 // wtf nulls?
*/
L2Game_UseItem::L2Game_UseItem()
{
this->_initNull();
}
L2Game_UseItem::L2Game_UseItem( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_UseItem::create( unsigned int oid )
{
this->writeReset();
this->writeUChar( 0x19 ); // packet type - UseItem
this->writeUInt( oid );
this->writeUInt( 0x00000000 );
return true;
}
unsigned int L2Game_UseItem::read_objectID()
{
if( !(this->canReadBytes(5)) ) return 0;
this->readReset();
this->readUChar(); // pcode
return this->readUInt();
}

View File

@@ -0,0 +1,17 @@
#ifndef L2GAME_USEITEM_H_
#define L2GAME_USEITEM_H_
#include "../L2GamePacket.h"
class L2Game_UseItem: public L2GamePacket
{
public:
L2Game_UseItem();
L2Game_UseItem( const unsigned char *bytes, unsigned int length );
public:
bool create( unsigned int oid );
public:
unsigned int read_objectID();
};
#endif

View File

@@ -0,0 +1,49 @@
#include "stdafx.h"
#include "L2Game_AuthLoginFail.h"
L2Game_AuthLoginFail::L2Game_AuthLoginFail()
{
_initNull();
}
L2Game_AuthLoginFail::L2Game_AuthLoginFail( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_AuthLoginFail::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x0A ) return false;
p_reasonCode = readUInt();
return true;
}
bool L2Game_AuthLoginFail::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x0A );
writeUInt( p_reasonCode );
return true;
}
void L2Game_AuthLoginFail::reasonCodeToString( int code, char *outString )
{
switch( code )
{
case REASON_NO_TEXT: strcpy( outString, "REASON_NO_TEXT" ); break;
case REASON_SYSTEM_ERROR_LOGIN_LATER: strcpy( outString, "REASON_SYSTEM_ERROR_LOGIN_LATER" ); break;
case REASON_PASSWORD_DOES_NOT_MATCH_THIS_ACCOUNT: strcpy( outString, "REASON_PASSWORD_DOES_NOT_MATCH_THIS_ACCOUNT" ); break;
case REASON_PASSWORD_DOES_NOT_MATCH_THIS_ACCOUNT2: strcpy( outString, "REASON_PASSWORD_DOES_NOT_MATCH_THIS_ACCOUNT2" ); break;
case REASON_ACCESS_FAILED_TRY_LATER: strcpy( outString, "REASON_ACCESS_FAILED_TRY_LATER" ); break;
case REASON_INCORRECT_ACCOUNT_INFO_CONTACT_CUSTOMER_SUPPORT: strcpy( outString, "REASON_INCORRECT_ACCOUNT_INFO_CONTACT_CUSTOMER_SUPPORT" ); break;
case REASON_ACCESS_FAILED_TRY_LATER2: strcpy( outString, "REASON_ACCESS_FAILED_TRY_LATER2" ); break;
case REASON_ACOUNT_ALREADY_IN_USE: strcpy( outString, "REASON_ACOUNT_ALREADY_IN_USE" ); break;
case REASON_ACCESS_FAILED_TRY_LATER3: strcpy( outString, "REASON_ACCESS_FAILED_TRY_LATER3" ); break;
case REASON_ACCESS_FAILED_TRY_LATER4: strcpy( outString, "REASON_ACCESS_FAILED_TRY_LATER4" ); break;
case REASON_ACCESS_FAILED_TRY_LATER5: strcpy( outString, "REASON_ACCESS_FAILED_TRY_LATER5" ); break;
default: strcpy( outString, "REASON_UNKNOWN" ); break;
}
}

View File

@@ -0,0 +1,32 @@
#ifndef L2GAME_AUTHLOGINFAIL_H_
#define L2GAME_AUTHLOGINFAIL_H_
#include "../L2GamePacket.h"
class L2Game_AuthLoginFail: public L2GamePacket
{
public:
static const int REASON_NO_TEXT = 0;
static const int REASON_SYSTEM_ERROR_LOGIN_LATER = 1;
static const int REASON_PASSWORD_DOES_NOT_MATCH_THIS_ACCOUNT = 2;
static const int REASON_PASSWORD_DOES_NOT_MATCH_THIS_ACCOUNT2 = 3;
static const int REASON_ACCESS_FAILED_TRY_LATER = 4;
static const int REASON_INCORRECT_ACCOUNT_INFO_CONTACT_CUSTOMER_SUPPORT = 5;
static const int REASON_ACCESS_FAILED_TRY_LATER2 = 6;
static const int REASON_ACOUNT_ALREADY_IN_USE = 7;
static const int REASON_ACCESS_FAILED_TRY_LATER3 = 8;
static const int REASON_ACCESS_FAILED_TRY_LATER4 = 9;
static const int REASON_ACCESS_FAILED_TRY_LATER5 = 10;
public:
L2Game_AuthLoginFail();
L2Game_AuthLoginFail( const unsigned char *bytes, unsigned int length );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
static void reasonCodeToString( int code, char *outString );
public:
unsigned int p_reasonCode;
};
#endif

View File

@@ -0,0 +1,42 @@
#include "stdafx.h"
#include "L2Game_CharCreateFail.h"
L2Game_CharCreateFail::L2Game_CharCreateFail()
{
_initNull();
}
L2Game_CharCreateFail::L2Game_CharCreateFail( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharCreateFail::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x10 ) return false;
p_reasonCode = readUInt();
return true;
}
bool L2Game_CharCreateFail::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x10 );
writeUInt( p_reasonCode );
return true;
}
void L2Game_CharCreateFail::reasonCodeToString( int code, char *outString )
{
switch( code )
{
case REASON_CREATION_FAILED: strcpy( outString, "REASON_CREATION_FAILED" ); break;
case REASON_TOO_MANY_CHARACTERS: strcpy( outString, "REASON_TOO_MANY_CHARACTERS" ); break;
case REASON_NAME_ALREADY_EXISTS: strcpy( outString, "REASON_NAME_ALREADY_EXISTS" ); break;
case REASON_16_ENG_CHARS: strcpy( outString, "REASON_16_ENG_CHARS" ); break;
default: strcpy( outString, "REASON_UNKNOWN" ); break;
}
}

View File

@@ -0,0 +1,28 @@
#ifndef L2GAME_CHARCREATEFAIL_H_
#define L2GAME_CHARCREATEFAIL_H_
#include "../L2GamePacket.h"
class L2Game_CharCreateFail: public L2GamePacket
{
public:
static const int REASON_CREATION_FAILED = 0x00;
static const int REASON_TOO_MANY_CHARACTERS = 0x01;
static const int REASON_NAME_ALREADY_EXISTS = 0x02;
static const int REASON_16_ENG_CHARS = 0x03;
static const int REASON_INCORRECT_NAME = 0x04;
static const int REASON_CREATE_NOT_ALLOWED = 0x05;
static const int REASON_CHOOSE_ANOTHER_SVR = 0x06;
public:
L2Game_CharCreateFail();
L2Game_CharCreateFail( const unsigned char *bytes, unsigned int length );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
static void reasonCodeToString( int code, char *outString );
public:
unsigned int p_reasonCode;
};
#endif

View File

@@ -0,0 +1,30 @@
#include "stdafx.h"
#include "L2Game_CharCreateSuccess.h"
L2Game_CharCreateSuccess::L2Game_CharCreateSuccess()
{
_initNull();
}
L2Game_CharCreateSuccess::L2Game_CharCreateSuccess( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharCreateSuccess::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x0F ) return false;
if( readUInt() != 0x01 ) return false;
return true;
}
bool L2Game_CharCreateSuccess::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x0F );
writeUInt( 0x01 );
return true;
}

View File

@@ -0,0 +1,16 @@
#ifndef L2GAME_CHARCREATEOK_H_
#define L2GAME_CHARCREATEOK_H_
#include "../L2GamePacket.h"
class L2Game_CharCreateSuccess: public L2GamePacket
{
public:
L2Game_CharCreateSuccess();
L2Game_CharCreateSuccess( const unsigned char *bytes, unsigned int length );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
};
#endif

View File

@@ -0,0 +1,41 @@
#include "stdafx.h"
#include "L2Game_CharDeleteFail.h"
L2Game_CharDeleteFail::L2Game_CharDeleteFail()
{
_initNull();
}
L2Game_CharDeleteFail::L2Game_CharDeleteFail( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharDeleteFail::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x1E ) return false;
p_reasonCode = readUInt();
return true;
}
bool L2Game_CharDeleteFail::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x1E );
writeUInt( p_reasonCode );
return true;
}
void L2Game_CharDeleteFail::reasonCodeToString( int code, char *outString )
{
switch( code )
{
case REASON_DELETION_FAILED: strcpy( outString, "REASON_DELETION_FAILED" ); break;
case REASON_YOU_MAY_NOT_DELETE_CLAN_MEMBER: strcpy( outString, "REASON_YOU_MAY_NOT_DELETE_CLAN_MEMBER" ); break;
case REASON_CLAN_LEADERS_MAY_NOT_BE_DELETED: strcpy( outString, "REASON_CLAN_LEADERS_MAY_NOT_BE_DELETED" ); break;
default: strcpy( outString, "REASON_UNKNOWN" ); break;
}
}

View File

@@ -0,0 +1,24 @@
#ifndef L2GAME_CHARDELETEFAIL_H_
#define L2GAME_CHARDELETEFAIL_H_
#include "../L2GamePacket.h"
class L2Game_CharDeleteFail: public L2GamePacket
{
public:
static const int REASON_DELETION_FAILED = 0x01;
static const int REASON_YOU_MAY_NOT_DELETE_CLAN_MEMBER = 0x02;
static const int REASON_CLAN_LEADERS_MAY_NOT_BE_DELETED = 0x03;
public:
L2Game_CharDeleteFail();
L2Game_CharDeleteFail( const unsigned char *bytes, unsigned int length );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
static void reasonCodeToString( int code, char *outString );
public:
unsigned int p_reasonCode;
};
#endif

View File

@@ -0,0 +1,16 @@
#include "stdafx.h"
#include "L2Game_CharDeleteSuccess.h"
L2Game_CharDeleteSuccess::L2Game_CharDeleteSuccess()
{
_initNull();
}
L2Game_CharDeleteSuccess::L2Game_CharDeleteSuccess( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}

View File

@@ -0,0 +1,14 @@
#ifndef L2GAME_CHARDELETESUCCESS_H_
#define L2GAME_CHARDELETESUCCESS_H_
#include "../L2GamePacket.h"
class L2Game_CharDeleteSuccess: public L2GamePacket
{
public:
L2Game_CharDeleteSuccess();
L2Game_CharDeleteSuccess( const unsigned char *bytes, unsigned int length );
// nothing to parse - just trigger
};
#endif

View File

@@ -0,0 +1,124 @@
#include "stdafx.h"
#include "L2Game_CharSelected.h"
L2Game_CharSelected::L2Game_CharSelected()
{
_initNull();
}
L2Game_CharSelected::L2Game_CharSelected( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
bool L2Game_CharSelected::parse( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
if( !this->canReadBytes( 200 ) ) return false; // must be at least 200 bytes
readReset();
readUChar(); // 0x0b CharSelected
wcscpy( p_char_name, readUnicodeStringPtr() ); // char name
p_charId = readUInt(); // char id (objectId)
wcscpy( p_title, readUnicodeStringPtr() ); // title
p_sessionId = readUInt(); // sessionId
p_clanId = readUInt(); // clanId
readD(); // 0x00 (maybe allyId?)
p_sex = readD();
p_race = readD();
p_classId = readUInt();
p_isActive = readD();
p_x = readD();
p_y = readD();
p_z = readD();
p_curHp = readF();
p_curMp = readF();
p_sp = readUInt();
p_exp = readUInt64();
p_level = readD();
p_karma = readD();
p_PK_kills = readD();
p_INT = readD();
p_STR = readD();
p_CON = readD();
p_MEN = readD();
p_DEX = readD();
p_WIT = readD();
readD(); // writeD( 0x0451 ); // game time?
readD(); // writeD( 0x00 ); // 0x00
readD(); // writeD( classId ); // classId already read?
//writeD(0x00); // 4 x 0x00
//writeD(0x00);
//writeD(0x00);
//writeD(0x00);
readD(); readD(); readD(); readD();
//writeB(new byte[64]); // some 64 bytes
int i;
for( i=0; i<16; i++ ) readD(); // read 4 x 16 = 64 bytes
p_opcodeObfuscatorSeed = readUInt();
return true;
}
bool L2Game_CharSelected::create( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
writeReset();
writeC(0x0b);
writeS( p_char_name );
writeD( p_charId );
writeS( p_title );
writeD( p_sessionId ); // playOkID1
writeD( p_clanId );
writeD( 0x00 ); // maybe allyId?
writeD( p_sex );
writeD( p_race );
writeD( p_classId );
writeD( p_isActive ); // active ??
writeD( p_x );
writeD( p_y );
writeD( p_z );
writeF( p_curHp );
writeF( p_curMp );
writeD( p_sp );
writeQ( p_exp );
writeD( p_level );
writeD( p_karma );
writeD( p_PK_kills );
writeD( p_INT );
writeD( p_STR );
writeD( p_CON );
writeD( p_MEN );
writeD( p_DEX );
writeD( p_WIT );
writeD( 0x0451 ); //?
writeD( 0x00 ); // some constants
writeD( p_classId );
writeD(0x00); // 4 x 0x00
writeD(0x00);
writeD(0x00);
writeD(0x00);
//writeB(new byte[64]); // some 64 bytes
unsigned char *rndbuf = (unsigned char *)malloc( 64 );
writeBytes( rndbuf, 64 );
free( rndbuf );
writeD( p_opcodeObfuscatorSeed ); // writeD(0x00);
return true;
}

View File

@@ -0,0 +1,43 @@
#ifndef L2GAME_CHARSELECTED_H_
#define L2GAME_CHARSELECTED_H_
#include "../L2GamePacket.h"
class L2Game_CharSelected : public L2GamePacket
{
public:
L2Game_CharSelected();
L2Game_CharSelected( const unsigned char *bytes, unsigned int length );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
wchar_t p_char_name[128]; // char name
unsigned int p_charId; // char id (objectId)
wchar_t p_title[128]; // title (empty here)
unsigned int p_sessionId; // sessionId
unsigned int p_clanId; // clan id
int p_sex; // sex
int p_race; // race 0x01 - elf
unsigned int p_classId; // class Id
int p_isActive; // is Active
int p_x;
int p_y;
int p_z;
double p_curHp; // currentHp
double p_curMp; // currentMp
unsigned int p_sp; // sp
unsigned long long int p_exp; // exp
int p_level; // level (64)
int p_karma; // karma
int p_PK_kills; // PK kills
int p_INT; // INT
int p_STR; // STR
int p_CON; // CON
int p_MEN; // MEN
int p_DEX; // DEX
int p_WIT; // WIT
unsigned int p_opcodeObfuscatorSeed; // opcode obfuscator seed
};
#endif

View File

@@ -0,0 +1,109 @@
#include "stdafx.h"
#include "L2Game_CharSelectionInfo.h"
L2Game_CharSelectionInfo::L2Game_CharSelectionInfo()
{
this->_initNull();
}
L2Game_CharSelectionInfo::L2Game_CharSelectionInfo( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Game_CharSelectionInfo::read_nChars( unsigned int *ret )
{
if( !ret ) return false;
this->readReset();
if( !this->canReadBytes(10) ) return false;
this->readUChar(); // pcode
(*ret) = this->readUInt();
return true;
}
// ret can be NULL
bool L2Game_CharSelectionInfo::read_server_maxChars( unsigned int *ret )
{
if( !ret ) return false;
this->readReset();
if( !this->canReadBytes(10) ) return false;
this->readUChar(); // pcode
this->readUInt(); // nChars
if( ret ) (*ret) = this->readUInt();
this->readUChar(); // read 0x00
return true;
}
bool L2Game_CharSelectionInfo::read_next_charSelectInfoBlock( L2_VERSION l2_version,
struct L2Game_CharSelectionInfoBlock *c )
{
if( !c ) return false;
memset( c, 0, sizeof(L2Game_CharSelectionInfoBlock) );
// TODO: how to detect that packet may be incorrect?
// char info must be AT LEAST 280 bytes long (Hellbound)
if( !this->canReadBytes(280) ) return false;
const wchar_t *wstr = NULL;
int i = 0;
wstr = this->readUnicodeStringPtr();
if( !wstr ) return false;
wcsncpy( c->charName, wstr, 31 );
c->charID = this->readUInt();
wstr = this->readUnicodeStringPtr();
if( !wstr ) return false;
wcsncpy( c->accountName, wstr, 31 );
c->sessionID = readUInt();
c->clanID = readUInt();
readUInt(); // 0x00
c->sex = readUInt();
c->race = readUInt();
c->baseClassID = readUInt();
c->isActive = readUInt();
c->x = readInt();
c->y = readInt();
c->z = readInt();
c->HP_cur = readDouble();
c->MP_cur = readDouble();
c->SP = readUInt();
c->Exp = readUInt64();
c->level = readUInt();
c->karma = readUInt();
c->PK_kills = readUInt();
c->PVP_kills = readUInt();
for( i=0; i<7; i++ ) readUInt(); // 7 0x00
c->iid_hair_all = readUInt();
c->iid_R_ear = readUInt();
c->iid_L_ear = readUInt();
c->iid_neck = readUInt();
c->iid_R_finger = readUInt();
c->iid_L_finger = readUInt();
c->iid_head = readUInt();
c->iid_R_hand = readUInt();
c->iid_L_hand = readUInt();
c->iid_gloves = readUInt();
c->iid_chest = readUInt();
c->iid_legs = readUInt();
c->iid_feet = readUInt();
c->iid_back = readUInt();
c->iid_LR_hand = readUInt();
c->iid_hair = readUInt();
c->iid_hair_2 = readUInt();
c->iid_R_bracelet = readUInt();
c->iid_L_bracelet = readUInt();
for( i=0; i<6; i++ ) readUInt(); // DECO1 .. DECO6
if( l2_version >= L2_VERSION_T23 )
c->iid_belt = readUInt(); // Gracia Final T2.3
c->hairStyle = readUInt();
c->hairColor = readUInt();
c->face = readUInt();
c->HP_max = readDouble();
c->MP_max = readDouble();
c->deleteSeconds = readUInt();
c->classID = readUInt();
c->lastUsedChar = readUInt();
c->enchantEffect = readUChar();
c->augmentID = readUShort();
c->augmentSmth = readUShort();
c->transformID = readUInt();
return true;
}

View File

@@ -0,0 +1,74 @@
#ifndef L2GAME_CHARSELECTIONINFO_H_
#define L2GAME_CHARSELECTIONINFO_H_
#include "../L2GamePacket.h"
struct L2Game_CharSelectionInfoBlock
{
wchar_t charName[32];
unsigned int charID;
wchar_t accountName[32];
unsigned int sessionID;
unsigned int clanID;
unsigned int sex;
unsigned int race;
unsigned int baseClassID;
unsigned int isActive;
int x;
int y;
int z;
double HP_cur;
double MP_cur;
unsigned int SP;
unsigned long long Exp;
unsigned int level;
unsigned int karma;
unsigned int PK_kills;
unsigned int PVP_kills;
unsigned int iid_hair_all;
unsigned int iid_R_ear;
unsigned int iid_L_ear;
unsigned int iid_neck;
unsigned int iid_R_finger;
unsigned int iid_L_finger;
unsigned int iid_head;
unsigned int iid_R_hand;
unsigned int iid_L_hand;
unsigned int iid_gloves;
unsigned int iid_chest;
unsigned int iid_legs;
unsigned int iid_feet;
unsigned int iid_back;
unsigned int iid_LR_hand;
unsigned int iid_hair;
unsigned int iid_hair_2;
unsigned int iid_R_bracelet;
unsigned int iid_L_bracelet;
unsigned int iid_belt; // T2.3
unsigned int hairStyle;
unsigned int hairColor;
unsigned int face;
double HP_max;
double MP_max;
unsigned int deleteSeconds; ///< seconds left before char will be deleted, or 0 if char is not marked to deletion
unsigned int classID;
unsigned int lastUsedChar;
unsigned char enchantEffect;
unsigned short int augmentID;
unsigned short int augmentSmth;
unsigned int transformID;
};
class L2Game_CharSelectionInfo : public L2GamePacket
{
public:
L2Game_CharSelectionInfo();
L2Game_CharSelectionInfo( const unsigned char *bytes, unsigned int length );
public:
bool read_nChars( unsigned int *ret );
bool read_server_maxChars( unsigned int *ret ); // ret can be NULL
bool read_next_charSelectInfoBlock( L2_VERSION l2_version,
struct L2Game_CharSelectionInfoBlock *c );
};
#endif /*L2GAME_CHARSELECTIONINFO_H_*/

View File

@@ -0,0 +1,122 @@
#include "stdafx.h"
#include "L2Game_KeyPacket.h"
/**
* ==========================================
Retail NCSoft
19 00 // p.len 25
2E // pcode
01 // always const
42 55 77 8F C3 05 69 87 // xorkey first part
01 00 00 00 // always const
01 // possible Game Server ID - depends on game server ID
00 00 00 00 // always NULLs
XX XX XX XX // always different, non-nulls: opcode obfuscator
*/
L2Game_KeyPacket::L2Game_KeyPacket()
{
this->_initNull();
}
L2Game_KeyPacket::L2Game_KeyPacket( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
// key must point to buffer large enough to hold 8 bytes
bool L2Game_KeyPacket::read_key( unsigned char *key )
{
if( !key ) return false;
this->readReset();
if( this->canReadBytes(10) )
{
this->readUChar(); // packet type (0x0e in hellbound, 0x00 - interlude)
this->readUChar(); // 0x01 ?
return this->readBytes( key, 8 );
}
else return false;
}
unsigned char L2Game_KeyPacket::read_GameServerID()
{
if( !this->canReadBytes(5) ) return 0x00;
this->readUInt(); // 01 00 00 00 // always const
return this->readUChar(); // 01 // possible Game Server ID
}
unsigned int L2Game_KeyPacket::read_OpcodeObfuscator()
{
if( !this->canReadBytes(4) ) return 0x00000000;
this->readUInt(); // 00 00 00 00 // always 0x00000000, read 4 NULLs
return this->readUInt(); // XX XX XX XX // always different, opcode obfuscator
}
// keyPacket array points to key bytes received from KeyPacket (8 bytes)
// keyResult will hold resultig key (16 bytes)
void L2Game_KeyPacket::createInitialHellboundKey(
const unsigned char *keyPacket,
unsigned char *keyResult )
{
if( !keyPacket || !keyResult ) return;
// first 8 bytes of key are from KeyPacket
keyResult[0] = keyPacket[0];
keyResult[1] = keyPacket[1];
keyResult[2] = keyPacket[2];
keyResult[3] = keyPacket[3];
keyResult[4] = keyPacket[4];
keyResult[5] = keyPacket[5];
keyResult[6] = keyPacket[6];
keyResult[7] = keyPacket[7];
// last 8 bytes are constant in T1/T1.5/T2/T2.2/T2.3...
keyResult[8] = (unsigned char)0xc8;
keyResult[9] = (unsigned char)0x27;
keyResult[10] = (unsigned char)0x93;
keyResult[11] = (unsigned char)0x01;
keyResult[12] = (unsigned char)0xa1;
keyResult[13] = (unsigned char)0x6c;
keyResult[14] = (unsigned char)0x31;
keyResult[15] = (unsigned char)0x97;
}
/*** Format:
19 00 // plen = 25
2E // pcode
01 // 00 - wrong proto, 01 - proto OK
B6 4D 20 15 CE 0E BC 7A // 1st 8 bytes of crypto key
01 00 00 00 // 0x01
09 // game serverID
00 00 00 00 // wtf?
E3 D1 10 2F // obfuscation key ***/
bool L2Game_KeyPacket::parse( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER( ver );
readReset();
if( !canReadBytes( 19 ) ) return false; // packet size is at least 19 bytes O_o
getPacketType();
this->p_protocolIsOK = readUChar(); // 0x01 - proto OK, 0x00 - proto not supported
readBytes( this->p_initialKey, 8 ); // first 8 bytes of XOR key
readD(); // 0x00000001
this->p_serverId = readUChar(); // server ID
readD(); // 0x00000000;
this->p_obfuscatorSeed = readUInt(); // obfuscator seed
// add last 8 bytes of XOR key - they are constant
createInitialHellboundKey( p_initialKey, p_initialKey );
//
return true;
}
bool L2Game_KeyPacket::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER( ver );
writeReset();
setPacketType( 0x2E );
writeUChar( p_protocolIsOK );
writeBytes( p_initialKey, 8 );
writeD( 1 );
writeUChar( p_serverId );
writeD( 0 );
writeUInt( p_obfuscatorSeed );
return true;
}

View File

@@ -0,0 +1,32 @@
#ifndef L2GAME_KEYPACKET_H_
#define L2GAME_KEYPACKET_H_
#include "../L2GamePacket.h"
class L2Game_KeyPacket : public L2GamePacket
{
public:
L2Game_KeyPacket();
L2Game_KeyPacket( const unsigned char *bytes, unsigned int length );
public:
// key must point to buffer large enough to hold 8 bytes
bool read_key( unsigned char *key );
unsigned char read_GameServerID();
unsigned int read_OpcodeObfuscator();
public:
// keyPacket array points to key bytes received from KeyPacket (8 bytes)
// keyResult will hold resultig key (16 bytes)
static void createInitialHellboundKey(
const unsigned char *keyPacket,
unsigned char *keyResult );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned char p_protocolIsOK;
unsigned char p_initialKey[16];
unsigned char p_serverId;
unsigned int p_obfuscatorSeed;
};
#endif /*L2GAME_KEYPACKET_H_*/

View File

@@ -0,0 +1,80 @@
#include "stdafx.h"
#include "L2Game_NewCharacterSuccess.h"
/*
Server: Len 967 [NewCharacterSuccess]
C7 03
0D // opcode
0C 00 00 00 // number of templates
// [ for each template ]
00 00 00 00 // race
00 00 00 00 // class id
46 00 00 00 // 0x46
28 00 00 00 // base STR
0A 00 00 00 // 0x0A
46 00 00 00 // 0x46
1E 00 00 00 // base DEX
0A 00 00 00
46 00 00 00
2B 00 00 00 // base CON
0A 00 00 00
46 00 00 00
15 00 00 00 // base INT
0A 00 00 00
46 00 00 00
0B 00 00 00 // base WIT
0A 00 00 00
46 00 00 00
19 00 00 00 // base MEN
0A 00 00 00
*/
L2Game_NewCharacterSuccess::L2Game_NewCharacterSuccess()
{
_initNull();
}
L2Game_NewCharacterSuccess::L2Game_NewCharacterSuccess( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
int L2Game_NewCharacterSuccess::read_templatesCount()
{
readReset();
getPacketType();
return readInt();
}
bool L2Game_NewCharacterSuccess::read_nextCharacterTemplate( struct L2Game_NewCharacterTemplate *t )
{
if( !t ) return false;
// each template is 80 bytes length (20Ds)
if( !canReadBytes( 80 ) ) return false;
// read
t->race = readD();
t->classID = readD();
readD(); // 0x46
t->base_STR = readD();
readD(); // 0x0A
readD(); // 0x46
t->base_DEX = readD();
readD(); // 0x0A
readD(); // 0x46
t->base_CON = readD();
readD(); // 0x0A
readD(); // 0x46
t->base_INT = readD();
readD(); // 0x0A
readD(); // 0x46
t->base_WIT = readD();
readD(); // 0x0A
readD(); // 0x46
t->base_MEN = readD();
readD(); // 0x0A
return true;
}

View File

@@ -0,0 +1,28 @@
#ifndef H_L2GAME_NEWCHARACTERSUCCESS
#define H_L2GAME_NEWCHARACTERSUCCESS
#include "../L2GamePacket.h"
struct L2Game_NewCharacterTemplate
{
int race;
int classID;
int base_STR;
int base_DEX;
int base_CON;
int base_INT;
int base_WIT;
int base_MEN;
};
class L2Game_NewCharacterSuccess: public L2GamePacket
{
public:
L2Game_NewCharacterSuccess();
L2Game_NewCharacterSuccess( const unsigned char *bytes, unsigned int length );
public:
int read_templatesCount();
bool read_nextCharacterTemplate( struct L2Game_NewCharacterTemplate *t );
};
#endif

View File

@@ -0,0 +1,43 @@
#include "stdafx.h"
#include "L2Game_SSQInfo.h"
L2Game_SSQInfo::L2Game_SSQInfo()
{
_initNull();
}
L2Game_SSQInfo::L2Game_SSQInfo( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
/**
protected final void writeImpl()
{
writeC(0x73);
if (_state == 2) // Dawn Sky
{
writeH(258);
}
else if (_state == 1) // Dusk Sky
{
writeH(257);
}
else
{
writeH(256);
}
}
*/
unsigned short int L2Game_SSQInfo::read_SSQ_SkySatus()
{
if( this->canReadBytes( 3 ) )
{
this->getPacketType();
return this->readUShort();
}
else return SSQ_NORMAL_SKY;
}

View File

@@ -0,0 +1,19 @@
#ifndef L2GAME_SSQINFO_H_
#define L2GAME_SSQINFO_H_
#include "../L2GamePacket.h"
class L2Game_SSQInfo : public L2GamePacket
{
public:
static const unsigned short int SSQ_DAWN_SKY = 258;
static const unsigned short int SSQ_DUSK_SKY = 257;
static const unsigned short int SSQ_NORMAL_SKY = 256;
public:
L2Game_SSQInfo();
L2Game_SSQInfo( const unsigned char *bytes, unsigned int length );
public:
unsigned short int read_SSQ_SkySatus();
};
#endif /* L2GAME_SSQINFO_H_*/

207
l2packets/l2data/L2Data.cpp Normal file
View File

@@ -0,0 +1,207 @@
#include "stdafx.h"
#include "L2Data.h"
// Lineage II races
char *L2Race[L2MaxRaces];
// Lineage II classes
char *L2Class[L2MaxClasses];
// Sex :)
char *L2Sex[L2MaxSexes];
// Races pictures depending on sex
// L2MaxRacePics = L2MaxRaces * L2MaxSexes;
char *L2RacePic[L2MaxRacePics];
// NPC races/classes
// index is level of skill id = 4416
char *L2NPCRace[L2MaxNPCRaces];
void L2Data_init()
{
// (char *) conversion because gcc4 thinks that string constants like "Human" are (const char *)
// but really all these strings are used like (const char *) pointers, so it must be OK
L2Race[0] = (char *)"Human";
L2Race[1] = (char *)"Elf";
L2Race[2] = (char *)"Dark Elf";
L2Race[3] = (char *)"Orc";
L2Race[4] = (char *)"Dwarf";
L2Race[5] = (char *)"Kamael";
memset( L2Class, 0, sizeof(L2Class) );
L2Class[0] = (char *)"Human Fighter";
L2Class[1] = (char *)"Warrior";
L2Class[2] = (char *)"Gladiator";
L2Class[3] = (char *)"Warlord";
L2Class[4] = (char *)"Knight";
L2Class[5] = (char *)"Paladin";
L2Class[6] = (char *)"Dark Avenger";
L2Class[7] = (char *)"Rogue";
L2Class[8] = (char *)"Treasure Hunter";
L2Class[9] = (char *)"Hawkeye";
L2Class[10] = (char *)"Human Mystic";
L2Class[11] = (char *)"Human Wizard";
L2Class[12] = (char *)"Sorceror";
L2Class[13] = (char *)"Necromancer";
L2Class[14] = (char *)"Warlock";
L2Class[15] = (char *)"Cleric";
L2Class[16] = (char *)"Bishop";
L2Class[17] = (char *)"Prophet";
L2Class[18] = (char *)"Elven Fighter";
L2Class[19] = (char *)"Elven Knight";
L2Class[20] = (char *)"Temple Knight";
L2Class[21] = (char *)"Sword Singer";
L2Class[22] = (char *)"Elven Scout";
L2Class[23] = (char *)"Plains Walker";
L2Class[24] = (char *)"Silver Ranger";
L2Class[25] = (char *)"Elven Mystic";
L2Class[26] = (char *)"Elven Wizard";
L2Class[27] = (char *)"SpellSinger";
L2Class[28] = (char *)"Elemental Summoner";
L2Class[29] = (char *)"Elven Oracle";
L2Class[30] = (char *)"Elven Elder";
L2Class[31] = (char *)"Dark Fighter";
L2Class[32] = (char *)"Paulus Knight";
L2Class[33] = (char *)"Shillien Knight";
L2Class[34] = (char *)"BladeDancer";
L2Class[35] = (char *)"Assassin";
L2Class[36] = (char *)"Abyss Walker";
L2Class[37] = (char *)"Phantom Ranger";
L2Class[38] = (char *)"Dark Mystic";
L2Class[39] = (char *)"Dark Wizard";
L2Class[40] = (char *)"Spellhowler";
L2Class[41] = (char *)"Phantom Summoner";
L2Class[42] = (char *)"Shillien Oracle";
L2Class[43] = (char *)"Shillien Elder";
L2Class[44] = (char *)"Orc Fighter";
L2Class[45] = (char *)"Orc Raider";
L2Class[46] = (char *)"Destroyer";
L2Class[47] = (char *)"Orc Monk";
L2Class[48] = (char *)"Tyrant";
L2Class[49] = (char *)"Orc Mystic";
L2Class[50] = (char *)"Orc Shaman";
L2Class[51] = (char *)"Overlord";
L2Class[52] = (char *)"Warcryer";
L2Class[53] = (char *)"Dwarven Fighter";
L2Class[54] = (char *)"Scavenger";
L2Class[55] = (char *)"Bounty Hunter";
L2Class[56] = (char *)"Artisan";
L2Class[57] = (char *)"Warsmith";
//
// indexes [ 58 .. 87 ] unused
//
L2Class[88] = (char *)"Duelist";
L2Class[89] = (char *)"Dreadnought";
L2Class[90] = (char *)"Phoenix Knight";
L2Class[91] = (char *)"HellKnight";
L2Class[92] = (char *)"Sagittarius";
L2Class[93] = (char *)"Adventurer";
L2Class[94] = (char *)"Archmage";
L2Class[95] = (char *)"Soultaker";
L2Class[96] = (char *)"Arcana Lord";
L2Class[97] = (char *)"Cardinal";
L2Class[98] = (char *)"Hierophant";
L2Class[99] = (char *)"Eva's Templar";
L2Class[100] = (char *)"Sword Muse";
L2Class[101] = (char *)"Wind Rider";
L2Class[102] = (char *)"Moonlight Sentinel";
L2Class[103] = (char *)"Mystic Muse";
L2Class[104] = (char *)"Elemental Master";
L2Class[105] = (char *)"Eva's Saint";
L2Class[106] = (char *)"Shillien Templar";
L2Class[107] = (char *)"Spectral Dancer";
L2Class[108] = (char *)"Ghost Hunter";
L2Class[109] = (char *)"Ghost Sentinel";
L2Class[110] = (char *)"Storm Screamer";
L2Class[111] = (char *)"Spectral Master";
L2Class[112] = (char *)"Shillien Saint";
L2Class[113] = (char *)"Titan";
L2Class[114] = (char *)"Grand Khauatari";
L2Class[115] = (char *)"Dominator";
L2Class[116] = (char *)"Doomcryer";
L2Class[117] = (char *)"Fortune Seeker";
L2Class[118] = (char *)"Maestro";
//
// indexes [ 119 .. 122 ] unused
//
L2Class[123] = (char *)"Kamael Male Soldier";
L2Class[124] = (char *)"Kamael Female Soldier";
L2Class[125] = (char *)"Trooper";
L2Class[126] = (char *)"Warder";
L2Class[127] = (char *)"Berserker";
L2Class[128] = (char *)"Soulbreaker (Male)"; //"Male Soulbreaker";
L2Class[129] = (char *)"Soulbreaker (Female)"; //"Female Soulbreaker";
L2Class[130] = (char *)"Arbalester";
L2Class[131] = (char *)"Doombringer";
L2Class[132] = (char *)"Soulhound (Male)"; // male
L2Class[133] = (char *)"Soulhound (Female)"; // female
L2Class[134] = (char *)"Trickster"; // female
L2Class[135] = (char *)"Inspector";
L2Class[136] = (char *)"Judicator";
L2Sex[0] = (char *)"Male";
L2Sex[1] = (char *)"Female";
L2RacePic[0] = (char *)"human_male";
L2RacePic[1] = (char *)"human_female";
L2RacePic[2] = (char *)"elf_male";
L2RacePic[3] = (char *)"elf_female";
L2RacePic[4] = (char *)"darkelf_male";
L2RacePic[5] = (char *)"darkelf_female";
L2RacePic[6] = (char *)"orc_male";
L2RacePic[7] = (char *)"orc_female";
L2RacePic[8] = (char *)"dwarf_male";
L2RacePic[9] = (char *)"dwarf_female";
L2RacePic[10] = (char *)"kamael_male";
L2RacePic[11] = (char *)"kamael_female";
L2NPCRace[0] = (char *)"NPC race index 0 not used";
L2NPCRace[1] = (char *)"Undead";
L2NPCRace[2] = (char *)"Magic Creatures";
L2NPCRace[3] = (char *)"Beasts";
L2NPCRace[4] = (char *)"Animals";
L2NPCRace[5] = (char *)"Plants";
L2NPCRace[6] = (char *)"Humanoids";
L2NPCRace[7] = (char *)"Spirits";
L2NPCRace[8] = (char *)"Angels";
L2NPCRace[9] = (char *)"Demons";
L2NPCRace[10] = (char *)"Dragons";
L2NPCRace[11] = (char *)"Giants";
L2NPCRace[12] = (char *)"Bugs";
L2NPCRace[13] = (char *)"Fairies";
L2NPCRace[14] = (char *)"Humans";
L2NPCRace[15] = (char *)"Elves";
L2NPCRace[16] = (char *)"Dark Elves";
L2NPCRace[17] = (char *)"Orcs";
L2NPCRace[18] = (char *)"Dwarves";
L2NPCRace[19] = (char *)"Others";
L2NPCRace[20] = (char *)"Non-living Beings";
L2NPCRace[21] = (char *)"Siege Weapons";
L2NPCRace[22] = (char *)"Defending Army";
L2NPCRace[23] = (char *)"Mercenaries";
L2NPCRace[24] = (char *)"Unknown Creature";
}
const char *L2Data_getRace( int raceID )
{
if( (raceID<0) || (raceID>=L2MaxRaces) ) return NULL;
return L2Race[raceID];
}
const char *L2Data_getClass( int classID )
{
if( (classID<0) || (classID>=L2MaxClasses) ) return NULL;
return L2Class[classID];
}
const char *L2Data_getSex( int sexID )
{
if( (sexID<0) || (sexID>=L2MaxSexes) ) return NULL;
return L2Sex[sexID];
}
const char *L2Data_getRacePic( int raceID, int sexID )
{
int picID = raceID*2 + sexID;
if( (picID<0) || (picID>=L2MaxRacePics) ) return NULL;
return L2RacePic[picID];
}
const char *L2Data_getNPCRace( int npcRaceID )
{
if( (npcRaceID<0) || (npcRaceID>=L2MaxNPCRaces) ) return NULL;
return L2NPCRace[npcRaceID];
}

51
l2packets/l2data/L2Data.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef L2DATA_H_
#define L2DATA_H_
#include "L2Data_Recipes.h"
#define L2MaxRaces 6
#define L2MaxClasses 137
#define L2MaxSexes 2
#define L2MaxRacePics 12
#define L2MaxNPCRaces 25
void L2Data_init();
const char *L2Data_getRace( int raceID );
const char *L2Data_getClass( int classID );
const char *L2Data_getSex( int sexID );
const char *L2Data_getRacePic( int raceID, int sexID );
const char *L2Data_getNPCRace( int npcRaceID );
void L2Data_SM_init();
void L2Data_SM_free();
const char *L2Data_SM_get( unsigned int systemMessageID );
bool L2Data_DB_Init( char *outErrMsg,
const char *items_db_filename,
const char *mobs_db_filename,
const char *skills_db_filename );
void L2Data_DB_Free();
// title can be NULL
bool L2Data_DB_GetNPCNameTitleByID( unsigned int npcID, char *name, char *title );
// pic can be NULL
bool L2Data_DB_GetItemNamePicByID( unsigned int itemID, char *name, char *pic );
bool L2Data_DB_GetSkillNameByID( unsigned int skillID, char *name );
typedef struct st_L2Data_DB_Result
{
int rowCount; // row count in result set
int colCount; // columns count in result set
char ***rows; // row data: row[0] is 1st row; row[0][0] is 1st column; row[0][0][0] is 1st char in string
// input parameter
int inMaxRowsToGet; // queries do not change this parameter.
} L2Data_DB_Result, *PL2Data_DB_Result;
void L2Data_DB_Free_Result( L2Data_DB_Result *pResult );
bool L2Data_DB_Query_NPCs_ByName( const char *request, L2Data_DB_Result *pResult );
bool L2Data_DB_Query_Items_ByName( const char *request, L2Data_DB_Result *pResult );
bool L2Data_DB_Query_Skills_ByName( const char *request, L2Data_DB_Result *pResult );
#endif /* L2DATA_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
#ifndef H_RECIPEDATA
#define H_RECIPEDATA
class L2Data_RecipeInfo
{
public:
L2Data_RecipeInfo() { name[0] = 0; itemID = rec_itemID = 0; level = resultCount = mpCost = successRate; }
public:
char name[128];
unsigned int itemID;
unsigned int rec_itemID;
int level;
int resultCount;
int mpCost;
int successRate;
};
#define MAX_RECIPE_ID 910
void L2Data_InitRecipes();
bool L2Data_GetRecipeInfoForRecID( int recID, L2Data_RecipeInfo *pInfo );
#endif

View File

@@ -0,0 +1,377 @@
#include "stdafx.h"
#include "L2Data.h"
#include "sqlite3.h"
//char l2data_db_filename
int l2data_sqlite3_was_init = 0;
sqlite3 *l2data_sqlite3_conn_items = NULL;
sqlite3 *l2data_sqlite3_conn_npcs = NULL;
sqlite3 *l2data_sqlite3_conn_skills = NULL;
// synchronisation
#ifdef L2PACKETS_WINDOWS
CRITICAL_SECTION l2data_db_cs;
#endif
bool L2Data_DB_Init( char *outErrMsg,
const char *items_db_filename,
const char *mobs_db_filename,
const char *skills_db_filename )
{
if( outErrMsg ) outErrMsg[0] = 0;
if( !l2data_sqlite3_was_init )
{
// test for threadsafe
if( sqlite3_threadsafe() == 0 )
{
fprintf( stderr, "WARNING: sqlite3 is not configured to use thread-safe operations!\n" );
if( outErrMsg ) strcat( outErrMsg, "sqlite3 is not configured threadsafe! " );
}
//
int r = 0;
const char *errmsg = NULL;
// items
r = sqlite3_open( items_db_filename, &l2data_sqlite3_conn_items );
if( r != SQLITE_OK )
{
errmsg = sqlite3_errmsg( l2data_sqlite3_conn_items );
if( outErrMsg && errmsg ) strcat( outErrMsg, errmsg );
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
return false;
}
// npcs
r = sqlite3_open( mobs_db_filename, &l2data_sqlite3_conn_npcs );
if( r != SQLITE_OK )
{
errmsg = sqlite3_errmsg( l2data_sqlite3_conn_npcs );
if( outErrMsg && errmsg ) strcat( outErrMsg, errmsg );
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
sqlite3_close( l2data_sqlite3_conn_npcs );
l2data_sqlite3_conn_npcs = NULL;
return false;
}
// skills
r = sqlite3_open( skills_db_filename, &l2data_sqlite3_conn_skills );
if( r != SQLITE_OK )
{
errmsg = sqlite3_errmsg( l2data_sqlite3_conn_skills );
if( outErrMsg && errmsg ) strcat( outErrMsg, errmsg );
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
sqlite3_close( l2data_sqlite3_conn_npcs );
l2data_sqlite3_conn_npcs = NULL;
sqlite3_close( l2data_sqlite3_conn_skills );
l2data_sqlite3_conn_skills = NULL;
return false;
}
//
l2data_sqlite3_was_init = 1;
#ifdef L2PACKETS_WINDOWS
InitializeCriticalSection( &l2data_db_cs );
#endif
return true;
}
return true;
}
#ifdef L2PACKETS_WINDOWS
void L2Data_DB_Lock() { EnterCriticalSection( &l2data_db_cs ); }
void L2Data_DB_UnLock() { LeaveCriticalSection( &l2data_db_cs ); }
#endif
#ifdef L2PACKETS_LINUX
// TODO: lock/unlock semaphore (mutex?)
// FIXED: (?) uses SQLITE_THREADSAFE definition to sqlite3 library
void L2Data_DB_Lock()
{
}
void L2Data_DB_UnLock()
{
}
#endif
void L2Data_DB_Free()
{
if( l2data_sqlite3_was_init )
{
L2Data_DB_Lock();
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
sqlite3_close( l2data_sqlite3_conn_npcs );
l2data_sqlite3_conn_npcs = NULL;
sqlite3_close( l2data_sqlite3_conn_skills );
l2data_sqlite3_conn_skills = NULL;
l2data_sqlite3_was_init = 0;
L2Data_DB_UnLock();
#ifdef L2PACKETS_WINDOWS
DeleteCriticalSection( &l2data_db_cs );
#endif
#ifdef L2PACKETS_LINUX
// TODO: linux: delete sync object
#endif
}
}
typedef struct st_L2DATA_2PARAM
{
char *param1;
char *param2;
} L2DATA_2PARAM, *PL2DATA_2PARAM;
int L2Data_sqlite_callback_2param( void *arg, int argc, char **argv, char **argvCol )
{
argvCol = NULL; // unreferenced formal parameter
PL2DATA_2PARAM pst = (PL2DATA_2PARAM)arg;
if( !pst ) return 0;
if( !argv ) return 0;
if( argc == 1 )
{
if( pst->param1 ) pst->param1[0] = 0;
if( argv[0] && pst->param1 ) strcpy( pst->param1, argv[0] );
}
else if( argc == 2 )
{
if( pst->param1 ) pst->param1[0] = 0;
if( pst->param2 ) pst->param2[0] = 0;
if( argv[0] && pst->param1 ) strcpy( pst->param1, argv[0] );
if( argv[1] && pst->param2 ) strcpy( pst->param2, argv[1] );
}
return 0;
}
// title can be NULL
bool L2Data_DB_GetNPCNameTitleByID( unsigned int npcID, char *name, char *title )
{
if( !l2data_sqlite3_conn_npcs ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[128];
L2DATA_2PARAM st;
st.param1 = name;
st.param2 = title;
sprintf( query, "SELECT name,title FROM mobs WHERE id=%u", npcID );
int r = sqlite3_exec( l2data_sqlite3_conn_npcs, query, L2Data_sqlite_callback_2param, (void *)&st, &errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (get NPC by ID)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (get NPC by ID): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
// desc can be NULL
bool L2Data_DB_GetItemNamePicByID( unsigned int itemID, char *name, char *pic )
{
if( !l2data_sqlite3_conn_items ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[128];
L2DATA_2PARAM st;
st.param1 = name;
st.param2 = pic;
sprintf( query, "SELECT name,pic FROM items WHERE id=%u", itemID );
int r = sqlite3_exec( l2data_sqlite3_conn_items, query, L2Data_sqlite_callback_2param, (void *)&st, &errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (get item by id)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (get item by ID): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
bool L2Data_DB_GetSkillNameByID( unsigned int skillID, char *name )
{
if( !l2data_sqlite3_conn_skills ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[128];
L2DATA_2PARAM st;
st.param1 = name;
st.param2 = NULL;
sprintf( query, "SELECT name FROM skills WHERE id=%u", skillID );
int r = sqlite3_exec( l2data_sqlite3_conn_skills, query, L2Data_sqlite_callback_2param, (void *)&st, &errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (get skill by ID)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (get skill by ID): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
//#define L2DATA_RESULT_MAX_ROWS 64
int L2Data_sqlite_result_callback( void *pvResult, int colCount, char **colData, char **colName )
{
colName = NULL; // unreferenced formal parameter
L2Data_DB_Result *pResult = (L2Data_DB_Result *)pvResult;
if( !pResult ) return 0;
if( pResult->rowCount == 0 ) // current row number is 0, func called first time
{
pResult->colCount = colCount; // set column count in result set
// allocate row pointers array (maximum rows count limited :( )
pResult->rows = (char ***)malloc( pResult->inMaxRowsToGet * sizeof(char **) );
if( !pResult->rows ) return 0; // malloc() failed!
int i;
for( i=0; i<pResult->inMaxRowsToGet; i++ ) pResult->rows[i] = NULL;
}
if( pResult->rowCount >= pResult->inMaxRowsToGet ) return 0; // maximum reached, no more place
// allocate space for current row (colCount columns)
pResult->rows[ pResult->rowCount ] = (char **)malloc( colCount * sizeof( char* ) );
if( !pResult->rows[ pResult->rowCount ] ) return 0; // malloc failed! :(
// copy all coumns data to current row
int iCol;
for( iCol = 0; iCol < colCount; iCol++ )
{
if( colData[iCol] != NULL )
#ifdef L2PACKETS_WINDOWS
pResult->rows[ pResult->rowCount ][ iCol ] = _strdup( colData[iCol] ); // copy string to result set
#else // write own strdup() :)
pResult->rows[ pResult->rowCount ][ iCol ] = (char *)malloc( strlen( colData[iCol] ) + 1 );
if( pResult->rows[ pResult->rowCount ][ iCol ] ) strcpy( pResult->rows[ pResult->rowCount ][ iCol ], colData[iCol] );
#endif
else
pResult->rows[ pResult->rowCount ][ iCol ] = NULL; // NULL column value
}
//
pResult->rowCount++; // inc current row count in result set
return 0;
}
bool L2Data_DB_Query_NPCs_ByName( const char *request, L2Data_DB_Result *pResult )
{
if( !request || !pResult ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[256];
sprintf( query, "SELECT id,name,title,level FROM mobs WHERE name LIKE '%s' ORDER BY name", request );
// zero result set
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->rows = NULL;
// run query
int r = sqlite3_exec( l2data_sqlite3_conn_npcs, query,
L2Data_sqlite_result_callback,
(void *)pResult, // pass pointer to result set to callback
&errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (L2Data_DB_Query_NPCs_ByName)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (L2Data_DB_Query_NPCs_ByName): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
bool L2Data_DB_Query_Items_ByName( const char *request, L2Data_DB_Result *pResult )
{
if( !request || !pResult ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[256];
sprintf( query, "SELECT id,name,pic FROM items WHERE name LIKE '%s' ORDER BY name", request );
// zero result set
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->rows = NULL;
// run query
int r = sqlite3_exec( l2data_sqlite3_conn_items, query,
L2Data_sqlite_result_callback,
(void *)pResult, // pass pointer to result set to callback
&errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (L2Data_DB_Query_Items_ByName)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (L2Data_DB_Query_Items_ByName): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
bool L2Data_DB_Query_Skills_ByName( const char *request, L2Data_DB_Result *pResult )
{
if( !request || !pResult ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[256];
sprintf( query, "SELECT id,name FROM skills WHERE name LIKE '%s' ORDER BY name", request );
// zero result set
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->rows = NULL;
// run query
int r = sqlite3_exec( l2data_sqlite3_conn_skills, query,
L2Data_sqlite_result_callback,
(void *)pResult, // pass pointer to result set to callback
&errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (L2Data_DB_Query_Skills_ByName)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (L2Data_DB_Query_Skills_ByName): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
void L2Data_DB_Free_Result( L2Data_DB_Result *pResult )
{
if( !pResult ) return;
int rowCount = pResult->rowCount;
int colCount = pResult->colCount;
int ir, ic;
for( ir = 0; ir < rowCount; ir++ )
{
if( pResult->rows[ir] )
{
for( ic = 0; ic < colCount; ic++ )
{
if( pResult->rows[ir][ic] ) free( pResult->rows[ir][ic] );
}
free( pResult->rows[ir] );
}
}
free( pResult->rows );
pResult->rows = NULL;
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->inMaxRowsToGet = 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
#include "stdafx.h"
#include "L2Character.h"
#include "../game/L2GamePacket.h"
#include "../os/os_abstraction.h"
L2Character::L2Character()
{
setUnused();
}
L2Character::~L2Character()
{
setUnused();
}
L2Character::L2Character( const L2Character& other ): L2Object()
{
setUnused();
this->operator=( other );
}
const L2Character& L2Character::operator=( const L2Character& other )
{
if( this == &other ) return (*this);
L2Object::operator=( other );
// copy
level = other.level;
setName( other.charName );
setTitle( other.charTitle );
xDst = other.xDst;
yDst = other.yDst;
zDst = other.zDst;
heading = other.heading;
runSpeed = other.runSpeed;
walkSpeed = other.walkSpeed;
isRunning = other.isRunning;
isSitting = other.isSitting;
isAlikeDead = other.isAlikeDead;
isFlying = other.isFlying;
lastMoveTickTime = other.lastMoveTickTime;
s_STR = other.s_STR;
s_DEX = other.s_DEX;
s_CON = other.s_CON;
s_INT = other.s_INT;
s_WIT = other.s_WIT;
s_MEN = other.s_MEN;
pAtk = other.pAtk;
pDef = other.pDef;
mAtk = other.mAtk;
mDef = other.mDef;
pAtkSpd = other.pAtkSpd;
mAtkSpd = other.mAtkSpd;
accuracy = other.accuracy;
evasion = other.evasion;
critical = other.critical;
curHp = other.curHp;
maxHp = other.maxHp;
curMp = other.curMp;
maxMp = other.maxMp;
curCp = other.curCp;
maxCp = other.maxCp;
abnormalEffect = other.abnormalEffect;
targetObjectID = other.targetObjectID;
isInCombat = other.isInCombat;
collisionRadius = other.collisionRadius;
collisionHeight = other.collisionHeight;
pvpFlag = other.pvpFlag;
karma = other.karma;
clanID = other.clanID;
clanCrestID = other.clanCrestID;
clanCrestLargeID = other.clanCrestLargeID;
allyID = other.allyID;
allyCrestID = other.allyCrestID;
return (*this);
}
void L2Character::setUnused()
{
L2Object::setUnused();
stopMove();
charName[0] = charTitle[0] = 0;
level = 0;
heading = 0;
runSpeed = walkSpeed = isRunning = isSitting = isAlikeDead = 0;
lastMoveTickTime = 0;
s_STR = s_DEX = s_CON = s_INT = s_WIT = s_MEN = 0;
pAtk = pDef = mAtk = mDef = pAtkSpd = mAtkSpd = accuracy = evasion = critical = 0;
curHp = maxHp = curMp = maxMp = curCp = maxCp = 0.0;
abnormalEffect = 0;
targetObjectID = 0;
isInCombat = 0;
collisionRadius = collisionHeight = 1.0;
}
void L2Character::setName( const wchar_t *name )
{
if( name )
{
wcsncpy( charName, name, sizeof(charName)/sizeof(charName[0]) - 1 );
charName[ sizeof(charName)/sizeof(charName[0]) - 1 ] = 0;
}
}
void L2Character::setName( const char *name )
{
if( name )
{
#ifdef L2PACKETS_WINDOWS
_snwprintf( charName, sizeof(charName)/sizeof(charName[0]), L"%S", name );
#endif
#ifdef L2PACKETS_LINUX
swprintf( charName, sizeof(charName)/sizeof(charName[0]), L"%ls", name );
#endif
charName[ sizeof(charName)/sizeof(charName[0]) - 1 ] = 0;
}
}
void L2Character::setTitle( const wchar_t *title )
{
if( title )
{
wcsncpy( charTitle, title, sizeof(charTitle)/sizeof(charTitle[0]) - 1 );
charTitle[ sizeof(charTitle)/sizeof(charTitle[0]) - 1 ] = 0;
}
}
void L2Character::setTitle( const char *title )
{
if( title )
{
#ifdef L2PACKETS_WINDOWS
_snwprintf( charTitle, sizeof(charTitle)/sizeof(charTitle[0]), L"%S", title );
#endif
#ifdef L2PACKETS_LINUX
swprintf( charTitle, sizeof(charTitle)/sizeof(charTitle[0]), L"%ls", title );
#endif
charTitle[ sizeof(charTitle)/sizeof(charTitle[0]) - 1 ] = 0;
}
}
const wchar_t *L2Character::getName()
{
this->charName[sizeof(this->charName) - 1] = 0;
return (const wchar_t *)(this->charName);
}
const wchar_t *L2Character::getTitle()
{
this->charTitle[sizeof(this->charTitle) - 1] = 0;
return (const wchar_t *)(this->charTitle);
}
bool L2Character::parse_MoveToLocation( void *l2_game_packet )
{
L2GamePacket *p = (L2GamePacket *)l2_game_packet;
p->getPacketType();
unsigned int oid = p->readUInt();
if( oid != this->objectID ) return false; // not my move
xDst = p->readInt();
yDst = p->readInt();
zDst = p->readInt();
x = p->readInt();
y = p->readInt();
z = p->readInt();
this->lastMoveTickTime = OS_GetTickCount(); // last time when x,y,z, xDst,yDst,zDst were known exactly
return true;
}
void L2Character::processMoveTick()
{
unsigned long long int curTick = OS_GetTickCount();
unsigned long long int millisecsPassed = curTick - lastMoveTickTime;
if( millisecsPassed < 100 ) return;
lastMoveTickTime = curTick;
const int near_range = 50; // range in which point is reached
if( isMoving() )
{
int dx = xDst - x;
int dy = yDst - y;
int dz = zDst - z;
if( ((dx > -near_range)&&(dx < near_range)) &&
((dy > -near_range)&&(dy < near_range)) &&
((dz > -near_range)&&(dz < near_range)) ) // target ~~ reached?
{
stopMove();
return;
}
float useSpeed = (float)runSpeed;
if( isRunning ) useSpeed = (float)walkSpeed;
float secs = ((float)millisecsPassed) / 1000;
float movedDist = useSpeed * secs;
float totalDist = sqrtf( (float)(dx*dx + dy*dy) );
float k = totalDist / movedDist;
if( k < 1.1 ) // cannot be < 1
{
stopMove();
return;
}
float xDelta = (float)dx / k;
float yDelta = (float)dy / k;
x += (int)xDelta;
y += (int)yDelta;
}
}
void L2Character::startMoveTo( int mxd, int myd, int mzd, int mx, int my, int mz )
{
x = mx;
y = my;
z = mz;
xDst = mxd;
yDst = myd;
zDst = mzd;
lastMoveTickTime = OS_GetTickCount();
}

View File

@@ -0,0 +1,162 @@
#ifndef H_L2CHARACTER
#define H_L2CHARACTER
#include "L2Object.h"
/** \class L2Character
L2Character represents common properties for all moving objects in game:\n
treasure chests, doors, chairs, mobs, npcs, players...\n
\n
Every character is L2Object:\n
Every L2Object has its objectID and can also have its coordinates in L2World)\n
\n
Additionally:\n
Every L2Character has LEVEL!\n
Every L2Character has its charName and charTitle\n
Every L2Character has its heading\n
Every L2Character has moving speed in states: running, walking\n
Every L2Character has its move destination: xDst, yDst, zDst\n
Every L2Character can calc its position based on destnation point and time passed since last calc\n
Every L2Character has its base stats: INT WIT MEN CON STR DEX\n
Every L2Character has its stats: pAtk, mAtk, ..., curHp, maxHp, ...\n
Every L2Character has abnormalEffect\n
Every L2Character has its target\n
Every L2Character can be in combat\n
Every L2Character has its collision radius and height\n
Every L2Character has its pvpFlag, karma\n
Every L2Character has its clan, ally IDs and clan/ally crest IDs\n
*/
class L2Character : public L2Object
{
public:
/** Default constructor, just calls setUnused() (zeroes all members) */
L2Character();
/** Copy constructor
* \param other source to copy from */
L2Character( const L2Character& other );
/** Operator =
* \param other source to copy from
* \return reference to this object
*/
virtual const L2Character& operator=( const L2Character& other );
/** Default destructor, just calls setUnused() (zeroes all members) */
virtual ~L2Character();
public:
/** Initializes object's state (zeroes all members)
* \return none
*/
virtual void setUnused();
public:
/** MoveToLocation packet parser.
* MoveToLocation packet is sent when some object starts moving to some point.
* Updates x,y,z, xDst,yDst,zDst.
* Updates lastMoveTickTime (sets to current time).
* \param l2_game_packet pointer to L2GamePacket object to parse
* \return none
* \see lastMoveTickTime
*/
virtual bool parse_MoveToLocation( void *l2_game_packet );
/** Calculates current character position based on x, y, z, xDst, yDst, zDst,
* runSpeed / walkSpeed, isRunning, current time and last time when character coords were
* known exactly (from some packet or after previous calculation).
* Updates x,y,z and lastMoveTickTime (sets to current time).
* \return none
* \see lastMoveTickTime
*/
virtual void processMoveTick();
/** Starts 'moving' character: sets destination coords and current coords.
* Updates x,y,z,xDst,yDst,zDst,lastMoveTickTime.
* \param mxd,myd,mzd destination point coords
* \param mx,my,mz current char coords
* \return none
* \see lastMoveTickTime
*/
virtual void startMoveTo( int mxd, int myd, int mzd, int mx, int my, int mz );
/** sets xDst,yDst,zDst to 0x7FFFFFFF, indicating that character is not moving.
* \return none
* \see xDst,yDst,zDst
*/
virtual void stopMove() { xDst = 0x7FFFFFFF; yDst = 0x7FFFFFFF; zDst = 0x7FFFFFFF; }
/** moving test
* \return 1 if char is moving, 0 if not
* \see xDst,yDst,zDst
*/
virtual int isMoving() { return ((xDst != 0x7FFFFFFF) && (yDst != 0x7FFFFFFF) && (zDst!=0x7FFFFFFF)); }
public:
/** Sets char name.
* \param name new char name to set.
*/
virtual void setName( const wchar_t *name );
virtual void setName( const char *name );
/** Sets char title.
* \param title new char title to set.
*/
virtual void setTitle( const wchar_t *title );
virtual void setTitle( const char *title );
virtual const wchar_t *getName(); //< not really used
virtual const wchar_t *getTitle(); //< not really used
public:
int level; ///< character level
wchar_t charName[128]; ///< character name
wchar_t charTitle[128]; ///< character title (displayed above name in client ^^)
int xDst; ///< x-destination move coord (=0x7FFFFFFF if char is not moving)
int yDst; ///< y-destination move coord (=0x7FFFFFFF if char is not moving)
int zDst; ///< z-destination move coord (=0x7FFFFFFF if char is not moving)
unsigned int heading; ///< heading... not really used
int runSpeed; ///< run speed
int walkSpeed; ///< walk speed
int isRunning; ///< 1, if char is runing, 0 if walking
int isSitting; ///< 1, if char is sitting, 0 if standing
int isAlikeDead; ///< 1, if characted is dead or looks like dead (fake death)
int isFlying; ///< 1, if character is flying (?) T2.3
unsigned long long int lastMoveTickTime; ///< timer used to store last time when character coords were known exactly
int s_STR; ///< STR base stat
int s_DEX; ///< DEX base stat
int s_CON; ///< CON base stat
int s_INT; ///< INT base stat
int s_WIT; ///< WIT base stat
int s_MEN; ///< MEN base stat
int pAtk;
int pDef;
int mAtk;
int mDef;
int pAtkSpd;
int mAtkSpd;
int accuracy;
int evasion;
int critical;
double curHp; ///< current HP value
double maxHp; ///< maximum HP value
double curMp; ///< current MP value
double maxMp; ///< maximum MP value
double curCp; ///< current CP value
double maxCp; ///< maximum CP value
unsigned int abnormalEffect; ///< flags for visible buffs/defuffs: poison, medusa, bleed, ...
unsigned int targetObjectID; ///< objectID of object which is targeted by this character
int isInCombat; ///< 1, if char is in combat state, 0 if not
double collisionRadius;
double collisionHeight;
int pvpFlag;
int karma;
unsigned int clanID;
unsigned int clanCrestID;
unsigned int clanCrestLargeID;
unsigned int allyID;
unsigned int allyCrestID;
};
#endif

View File

@@ -0,0 +1,30 @@
#ifndef H_L2_CHAT_MESSAGE_TYPES
#define H_L2_CHAT_MESSAGE_TYPES
/** \class L2_CHAT_MESSAGE
* Defines constants used in S->C CreatureSay and C->S Say2 packets.\n
* Chat message type.
*/
class L2_CHAT_MESSAGE
{
public:
static const unsigned int ALL = 0;
static const unsigned int SHOUT = 1; //!
static const unsigned int TELL = 2;
static const unsigned int PARTY = 3; //#
static const unsigned int CLAN = 4; //@
static const unsigned int GM = 5;
static const unsigned int PETITION_PLAYER = 6; // used for petition
static const unsigned int PETITION_GM = 7; //* used for petition
static const unsigned int TRADE = 8; //+
static const unsigned int ALLIANCE = 9; //$
static const unsigned int ANNOUNCEMENT = 10;
static const unsigned int PARTYROOM_ALL = 16; //(Red)
static const unsigned int PARTYROOM_COMMANDER = 15; //(Yellow)
static const unsigned int HERO_VOICE = 17;
static const unsigned int L2_CHAT_MESSAGE_LAST = HERO_VOICE;
};
#endif

View File

@@ -0,0 +1,39 @@
#include "stdafx.h"
#include "L2ElementalInfo.h"
L2ElementalInfo::L2ElementalInfo()
{
clear();
}
L2ElementalInfo::L2ElementalInfo( const L2ElementalInfo& other )
{
clear();
this->operator=( other );
}
const L2ElementalInfo& L2ElementalInfo::operator=( const L2ElementalInfo& other )
{
if( this == &other ) return (*this);
attackElementType = other.attackElementType;
attackElementValue = other.attackElementValue;
defAttrFire = other.defAttrFire;
defAttrWater = other.defAttrWater;
defAttrWind = other.defAttrWind;
defAttrEarth = other.defAttrEarth;
defAttrHoly = other.defAttrHoly;
defAttrUnholy = other.defAttrUnholy;
return (*this);
}
void L2ElementalInfo::clear()
{
attackElementType = 0;
attackElementValue = 0;
defAttrFire = 0;
defAttrWater = 0;
defAttrWind = 0;
defAttrEarth = 0;
defAttrHoly = 0;
defAttrUnholy = 0;
}

View File

@@ -0,0 +1,23 @@
#ifndef H_L2_ELEMENTAL_INFO
#define H_L2_ELEMENTAL_INFO
class L2ElementalInfo
{
public:
L2ElementalInfo();
L2ElementalInfo( const L2ElementalInfo& other );
const L2ElementalInfo& operator=( const L2ElementalInfo& other );
public:
void clear();
public:
int attackElementType;
int attackElementValue;
int defAttrFire;
int defAttrWater;
int defAttrWind;
int defAttrEarth;
int defAttrHoly;
int defAttrUnholy;
};
#endif

View File

@@ -0,0 +1,118 @@
#include "stdafx.h"
#include "L2Experience.h"
double L2Experience::getExpPercent( long long exp )
{
double ret = 0.0;
#ifndef __GNUC__
const long long int exp_at_level[] =
#else
const double exp_at_level[] =
#endif
{
-1, // level 0 (unreachable)
0,
68,
363,
1168,
2884,
6038,
11287,
19423,
31378,
48229, //level 10
71201,
101676,
141192,
191452,
254327,
331864,
426284,
539995,
675590,
835854, //level 20
1023775,
1242536,
1495531,
1786365,
2118860,
2497059,
2925229,
3407873,
3949727,
4555766, //level 30
5231213,
5981539,
6812472,
7729999,
8740372,
9850111,
11066012,
12395149,
13844879,
15422851, //level 40
17137002,
18995573,
21007103,
23180442,
25524751,
28049509,
30764519,
33679907,
36806133,
40153995, //level 50
45524865,
51262204,
57383682,
63907585,
70852742,
80700339,
91162131,
102265326,
114038008,
126509030, //level 60
146307211,
167243291,
189363788,
212716741,
237351413,
271973532,
308441375,
346825235,
387197529,
429632402, //level 70
474205751,
532692055,
606319094,
696376867,
804219972,
931275828,
1151275834,
1511275834,
#ifdef __GNUC__
2099275834.0,
4200000000.0, //level 80
6300000000.0, //level 81
8820000000.0, //level 82
11844000000.0, //level 83
15472800000.0, //level 84
19827360000.0, //level 85
25314000000.0
#else
2099275834,
4200000000, //level 80
6300000000, //level 81
8820000000, //level 82
11844000000, //level 83
15472800000, //level 84
19827360000, //level 85
25314000000
#endif
};
int i = 0;
//int cur_level = 0;
for( i=0; i<86; i++ ) if( exp_at_level[i+1] > exp ) break;
//cur_level = i;
ret = 100.0 * (exp - exp_at_level[i]) / (exp_at_level[i+1] - exp_at_level[i]);
return ret;
}

View File

@@ -0,0 +1,28 @@
#ifndef H_L2_EXPERIENCE_
#define H_L2_EXPERIENCE_
/** \class L2Experience
* Some functions and constants to work with player exp values.
*/
class L2Experience
{
public:
/**
* Converts exp value to current exp percent.
* \param exp current experience value
* \return precent value in current level
*/
static double getExpPercent( long long exp );
public:
/**
* This is the first UNREACHABLE level.<BR>
* ex: If you want a max at 85 & 100.00%, you have to put 86.<BR><BR>
*/
static const int MAX_LEVEL = 86;
static const int MIN_NEWBIE_LEVEL = 6;
static const int MAX_NEWBIE_LEVEL = 39;
};
#endif

139
l2packets/l2world/L2Npc.cpp Normal file
View File

@@ -0,0 +1,139 @@
#include "stdafx.h"
#include "L2Npc.h"
#include "../l2data/L2Data.h"
#include "../game/L2GamePacket.h"
#include "../os/os_abstraction.h"
L2Npc::L2Npc()
{
setUnused();
}
L2Npc::~L2Npc()
{
setUnused();
}
L2Npc::L2Npc( const L2Npc& other ): L2Character()
{
setUnused();
operator=( other );
}
const L2Npc& L2Npc::operator=( const L2Npc& other )
{
if( this == &other ) return (*this);
L2Character::operator=( other );
templateID = other.templateID;
isAttackable = other.isAttackable;
iid_left_hand = other.iid_left_hand;
iid_right_hand = other.iid_right_hand;
iid_chest = other.iid_chest;
return (*this);
}
void L2Npc::setUnused()
{
L2Character::setUnused();
templateID = 0;
isAttackable = 0;
// weapon
iid_left_hand = iid_right_hand = iid_chest = 0;
}
void L2Npc::setNpcNameTitleByTemplate()
{
char db_name[256], db_title[256];
db_name[0] = db_title[0] = 0;
if( L2Data_DB_GetNPCNameTitleByID( templateID, db_name, db_title ) )
{
setName( db_name );
setTitle( db_title );
}
}
bool L2Npc::parse_NpcInfo( void *l2_game_packet, L2_VERSION l2_version )
{
if( !l2_game_packet ) return false;
L2GamePacket *p = (L2GamePacket *)l2_game_packet;
// parse
unsigned char ptype = p->getPacketType();
if( ptype != 0x0C ) return false; // 0x0C NpcInfo
//
objectID = p->readUInt();
templateID = p->readUInt() - 1000000; // ? :) L2J adds 1000000 to this field
isAttackable = p->readD(); // _isAttackable
x = p->readD();
y = p->readD();
z = p->readD();
heading = p->readUInt();
p->readD(); // 0x00
mAtkSpd = p->readD();
pAtkSpd = p->readD();
runSpeed = p->readD();
walkSpeed = p->readD();
p->readD(); // swim run speed
p->readD(); // swim walk speed
p->readD(); // fl run speed (?)
p->readD(); // fl walk speed (?)
p->readD(); // fly run speed (?) same as fl
p->readD(); // fly walk speed (?)
double moveSpeedMultiplier = p->readF();
double attackSpeedMultiplier = p->readF();
if( moveSpeedMultiplier > 0 )
{
runSpeed = (int)( ((double)runSpeed) * moveSpeedMultiplier );
walkSpeed = (int)( ((double)walkSpeed) * moveSpeedMultiplier );
}
if( attackSpeedMultiplier > 0 ) pAtkSpd = (int)( ((double)pAtkSpd) * attackSpeedMultiplier );
collisionRadius = p->readF();
collisionHeight = p->readF();
iid_right_hand = p->readUInt();
iid_chest = p->readUInt();
iid_left_hand = p->readUInt();
p->readC(); // has title
isRunning = p->readC();
isInCombat = p->readC();
isAlikeDead = p->readC();
p->readC(); // is summoned
setName( p->readUnicodeStringPtr() );
setTitle( p->readUnicodeStringPtr() );
p->readD(); // title color
p->readD(); // 0x00
pvpFlag = p->readD(); // pvp flag
abnormalEffect = p->readUInt();
clanID = p->readUInt(); // Gracia Final
clanCrestID = p->readUInt(); // Gracia Final
isFlying = p->readC(); // Gracia Final
p->readC(); // 0x00
p->readF(); // collisionRadius (again?)
p->readF(); // collisionHeight (again?)
p->readD(); // 0x00
p->readD(); // isFlying? (again?) Gracia Final
p->readD(); // 0x00
p->readD(); // pet form and skills (?)
// Gracia Final has some more to read
if( l2_version >= L2_VERSION_T23 )
{
p->readC(); // 0x01
p->readC(); // 0x01
p->readD(); // 0x00000000
}
// set last time when npc coordinates were known exactly
lastMoveTickTime = OS_GetTickCount();
return true;
}

67
l2packets/l2world/L2Npc.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef H_L2NPC
#define H_L2NPC
#include "L2Character.h"
/** \class L2Npc
Every L2Npc is L2Character:\n
Every L2Character is L2Object (has objectID, x, y, z)\n
Every L2Character has LEVEL!\n
Every L2Character has its charName and charTitle\n
Every L2Character has its heading\n
Every L2Character has moving speed in states: running, walking\n
Every L2Character has its move destination: xDst, yDst, zDst\n
Every l2Character can calc its position based on destnation point and time passed since last calc\n
Every L2Character has its base stats: INT WIT MEN CON STR DEX\n
Every L2Character has its stats: pAtk, mAtk, ..., curHp, maxHp, ...\n
Every L2Character has abnormalEffect\n
Every L2Character has its target\n
Every L2Character can be in combat\n
Every L2Character has its collision radius and height\n
\n
Additionally:\n
Every L2Npc has its NPC templateID\n
Every L2Npc can be attackable or not (attackable is mob, other is NPC. chooses default action on click)\n
Every L2Npc has weapon/shield or bow/arrow in left/right hand\n
*/
class L2Npc : public L2Character
{
public:
/** Default constructor calls setUnused() (zeroes all members) */
L2Npc();
/** Copy constructor
* \param other source to copy from
*/
L2Npc( const L2Npc& other );
/* Assigns all members of L2Npc class instance to other
* \param other source to copy from
* \return reference to this object */
virtual const L2Npc& operator=( const L2Npc& other );
/** Default destructor calls setUnused() (zeroes all members) */
virtual ~L2Npc();
public:
/** Initializes object's state (zeroes all members)
* \return none
*/
virtual void setUnused();
public:
/** Query database for name and title, using this object's templateID, and set them */
virtual void setNpcNameTitleByTemplate();
public:
bool parse_NpcInfo( void *l2_game_packet, L2_VERSION l2_version );
public:
unsigned int templateID; ///< NPC template ID
int isAttackable; ///< =1, if npc is auto attackable on double click (mob); 0 if double click begins chat with NPC (NPC)
unsigned int iid_left_hand; ///< item ID of left hand weapon item
unsigned int iid_chest; ///< item ID of chest (?)
unsigned int iid_right_hand; ///< item ID of right hand weapon item
};
#endif

View File

@@ -0,0 +1,27 @@
#include "stdafx.h"
#include "L2Object.h"
L2Object::~L2Object()
{
setUnused();
}
L2Object::L2Object( const L2Object& other )
{
this->operator=( other );
}
const L2Object& L2Object::operator=( const L2Object& other )
{
if( this == &other ) return (*this);
this->x = other.x;
this->y = other.y;
this->z = other.z;
this->objectID = other.objectID;
return (*this);
}
bool L2Object::operator==( const L2Object& other )
{
return this->objectID == other.objectID;
}

View File

@@ -0,0 +1,64 @@
#ifndef H_L2OBJECT
#define H_L2OBJECT
#include "../L2_versions.h"
/** \class L2Object
Every object has its objectID and can also have its coordinates in L2World
*/
class L2Object
{
public:
/** L2Object default constructor
*/
L2Object(): x(0), y(0), z(0), objectID(0) {}
/** L2Object copy constructor
* \param other copy source
*/
L2Object( const L2Object& other );
/** Assigns this->x,y,z,objectID to other's x,y,z,objectID
* \param other copy source
* \return reference to this object
*/
virtual const L2Object& operator=( const L2Object& other );
/** Compares objectIDs
* \param other object to compare with
* \return true, if objects are equal (equal objectIDs)
*/
virtual bool operator==( const L2Object& other );
/** Destructor calls setUnused()
* \see setUnused
*/
virtual ~L2Object();
public:
/** Sets object coordinates in world
* \param sx, sy, sz - new coordinates
* \return none
*/
virtual void setXYZ( int sx, int sy, int sz ) { x = sx; y = sy; z = sz; }
public:
/** Test objectID
* \return 1, if objectID == 0; 0 if objectID is nonzero.
*/
virtual int isUnused() const { return (objectID == 0); }
/** Initializes object's state, zeroes all members (sets coords to 0, objectID to 0)
* \return none
*/
virtual void setUnused() { objectID = 0; x = 0; y = 0; z = 0; }
public:
/** object's X coordinate */
int x;
/** object's Y coordinate */
int y;
/** object's Z coordinate */
int z;
/** objectID is unique in game world */
unsigned int objectID;
};
#endif

View File

@@ -0,0 +1,678 @@
#include "stdafx.h"
#include "L2Player.h"
#include "../l2data/L2Data.h"
#include "../game/L2GamePacket.h"
#include "../os/os_abstraction.h"
L2Player::L2Player()
{
setUnused();
}
L2Player::~L2Player()
{
setUnused();
}
L2Player::L2Player( const L2Player& other ): L2Character()
{
setUnused();
this->operator=( other );
}
const L2Player& L2Player::operator=( const L2Player& other )
{
if( this == &other ) return (*this); // self-assign
L2Character::operator=( other );
//
int i;
//
classID = other.classID;
baseClassID = other.baseClassID;
race = other.race;
sex = other.sex;
hairStyle = other.hairStyle;
hairColor = other.hairColor;
face = other.face;
experience = other.experience;
skill_points = other.skill_points;
curLoad = other.curLoad;
maxLoad = other.maxLoad;
pkKills = other.pkKills;
pvpKills = other.pvpKills;
enchantEffect = other.enchantEffect;
relation = other.relation;
autoAttackable = other.autoAttackable;
for( i=0; i<32; i++ )
{
paperdoll_oid[i] = other.paperdoll_oid[i];
paperdoll_iid[i] = other.paperdoll_iid[i];
paperdoll_augid[i] = other.paperdoll_augid[i];
}
isFakeDeath = other.isFakeDeath;
isFishing = other.isFishing;
fishX = other.fishX;
fishY = other.fishY;
fishZ = other.fishZ;
privateStoreType = other.privateStoreType;
wcsncpy( privateStoreMsgBuy, other.privateStoreMsgBuy, 64 );
privateStoreMsgBuy[63] = 0;
wcsncpy( privateStoreMsgSell, other.privateStoreMsgSell, 64 );
privateStoreMsgSell[63] = 0;
wcsncpy( privateStoreMsgRecipe, other.privateStoreMsgRecipe, 64 );
privateStoreMsgRecipe[63] = 0;
mountType = other.mountType;
mountNpcId = other.mountNpcId;
recomLeft = other.recomLeft;
recomHave = other.recomHave;
isNoble = other.isNoble;
isHero = other.isHero;
nameColor = other.nameColor;
titleColor = other.titleColor;
pledgeClass = other.pledgeClass;
pledgeType = other.pledgeType;
cursedWeaponId = other.cursedWeaponId;
clanRepScore = other.clanRepScore;
transformId = other.transformId;
agathionId = other.agathionId;
vehicleObjectId = other.vehicleObjectId;
hasDwarvenCraft = other.hasDwarvenCraft;
numCubics = other.numCubics;
for( i=0; i<4; i++ ) cubicId[i] = other.cubicId[i];
clanPrivs = other.clanPrivs;
inventoryLimit = other.inventoryLimit;
elements = other.elements;
fame = other.fame;
vitalityLevel = other.vitalityLevel;
//
return (*this);
}
void L2Player::setUnused()
{
L2Character::setUnused();
classID = baseClassID = 0;
clanID = clanCrestID = clanCrestLargeID = allyID = allyCrestID = 0;
race = sex = 0;
hairStyle = hairColor = face = 0;
experience = 0;
skill_points = 0;
curLoad = maxLoad = 0;
pkKills = pvpKills = 0;
relation = RELATION_NONE;
autoAttackable = 0;
int i;
for( i=0; i<32; i++ )
{
paperdoll_oid[i] = 0;
paperdoll_iid[i] = 0;
paperdoll_augid[i] = 0;
}
isFishing = 0;
fishX = fishY = fishZ = 0;
privateStoreType = 0;
privateStoreMsgBuy[0] = privateStoreMsgSell[0] = privateStoreMsgRecipe[0] = 0;
mountType = mountNpcId = 0;
recomLeft = recomHave = 0;
isNoble = isHero = 0;
nameColor = titleColor = 0;
pledgeClass = pledgeType = 0;
cursedWeaponId = transformId = agathionId = 0;
clanRepScore = 0;
vehicleObjectId = 0;
hasDwarvenCraft = 0;
numCubics = 0;
for( i=0; i<4; i++ ) cubicId[i] = 0;
clanPrivs = 0;
inventoryLimit = 0;
elements.clear();
}
void L2Player::getRaceStr( wchar_t *out ) const
{
if( !out ) return;
out[0] = 0;
const char *ansi = L2Data_getRace( this->race );
#ifdef L2PACKETS_WINDOWS
_snwprintf( out, 32, L"%S", ansi );
#endif
#ifdef L2PACKETS_LINUX
swprintf( out, 32, L"%ls", ansi );
#endif
out[31] = 0;
}
void L2Player::getSexStr( wchar_t *out ) const
{
if( !out ) return;
out[0] = 0;
const char *ansi = L2Data_getSex( this->sex );
#ifdef L2PACKETS_WINDOWS
_snwprintf( out, 32, L"%S", ansi );
#endif
#ifdef L2PACKETS_LINUX
swprintf( out, 32, L"%ls", ansi );
#endif
out[31] = 0;
}
void L2Player::getClassStr( wchar_t *out ) const
{
if( !out ) return;
out[0] = 0;
const char *ansi = L2Data_getClass( this->classID );
#ifdef L2PACKETS_WINDOWS
_snwprintf( out, 32, L"%S", ansi );
#endif
#ifdef L2PACKETS_LINUX
swprintf( out, 32, L"%ls", ansi );
#endif
out[31] = 0;
}
void L2Player::getBaseClassStr( wchar_t *out ) const
{
if( !out ) return;
out[0] = 0;
const char *ansi = L2Data_getClass( this->baseClassID );
#ifdef L2PACKETS_WINDOWS
_snwprintf( out, 32, L"%S", ansi );
#endif
#ifdef L2PACKETS_LINUX
swprintf( out, 32, L"%ls", ansi );
#endif
}
bool L2Player::parse_CharInfo( void *l2_game_packet, L2_VERSION l2_version )
{
if( !l2_game_packet ) return false;
int i;
L2GamePacket *p = (L2GamePacket *)l2_game_packet;
// parse
unsigned char ptype = p->getPacketType(); // 0x31
if( ptype != 0x31 ) return false;
x = p->readInt(); // x
y = p->readInt(); // y
z = p->readInt(); // z
p->readUInt(); // 0x00
objectID = p->readUInt(); // objectID
setName( p->readUnicodeStringPtr() ); // name
race = p->readUInt(); // race
sex = p->readInt(); // sex (0-male)
baseClassID = p->readUInt(); // base class
// paperdoll item IDs
paperdoll_iid[L2_PAPERDOLL_UNDER] = p->readUInt(); // PAPERDOLL_UNDER
paperdoll_iid[L2_PAPERDOLL_HEAD] = p->readUInt(); // PAPERDOLL_HEAD
paperdoll_iid[L2_PAPERDOLL_RHAND] = p->readUInt(); // PAPERDOLL_RHAND
paperdoll_iid[L2_PAPERDOLL_LHAND] = p->readUInt(); // PAPERDOLL_LHAND
paperdoll_iid[L2_PAPERDOLL_GLOVES] = p->readUInt(); // PAPERDOLL_GLOVES
paperdoll_iid[L2_PAPERDOLL_CHEST] = p->readUInt(); // PAPERDOLL_CHEST
paperdoll_iid[L2_PAPERDOLL_LEGS] = p->readUInt(); // PAPERDOLL_LEGS
paperdoll_iid[L2_PAPERDOLL_FEET] = p->readUInt(); // PAPERDOLL_FEET
paperdoll_iid[L2_PAPERDOLL_BACK] = p->readUInt(); // PAPERDOLL_BACK
paperdoll_iid[L2_PAPERDOLL_LRHAND] = p->readUInt(); // PAPERDOLL_LRHAND
paperdoll_iid[L2_PAPERDOLL_HAIR] = p->readUInt(); // PAPERDOLL_HAIR
paperdoll_iid[L2_PAPERDOLL_HAIR2] = p->readUInt(); // PAPERDOLL_HAIR2
// kamael
paperdoll_iid[L2_PAPERDOLL_RBRACELET] = p->readUInt(); // PAPERDOLL_RBRACELET
paperdoll_iid[L2_PAPERDOLL_LBRACELET] = p->readUInt(); // PAPERDOLL_LBRACELET
paperdoll_iid[L2_PAPERDOLL_DECO1] = p->readUInt(); // PAPERDOLL_DECO1
paperdoll_iid[L2_PAPERDOLL_DECO2] = p->readUInt(); // PAPERDOLL_DECO2
paperdoll_iid[L2_PAPERDOLL_DECO3] = p->readUInt(); // PAPERDOLL_DECO3
paperdoll_iid[L2_PAPERDOLL_DECO4] = p->readUInt(); // PAPERDOLL_DECO4
paperdoll_iid[L2_PAPERDOLL_DECO5] = p->readUInt(); // PAPERDOLL_DECO5
paperdoll_iid[L2_PAPERDOLL_DECO6] = p->readUInt(); // PAPERDOLL_DECO6
//
if( l2_version >= L2_VERSION_T23 )
paperdoll_iid[L2_PAPERDOLL_BELT] = p->readUInt(); // PAPERDOLL_BELT
// paperdoll augmentation IDs
paperdoll_augid[L2_PAPERDOLL_UNDER] = p->readUInt(); // PAPERDOLL_UNDER
paperdoll_augid[L2_PAPERDOLL_HEAD] = p->readUInt(); // PAPERDOLL_HEAD
paperdoll_augid[L2_PAPERDOLL_RHAND] = p->readUInt(); // PAPERDOLL_RHAND
paperdoll_augid[L2_PAPERDOLL_LHAND] = p->readUInt(); // PAPERDOLL_LHAND
paperdoll_augid[L2_PAPERDOLL_GLOVES] = p->readUInt(); // PAPERDOLL_GLOVES
paperdoll_augid[L2_PAPERDOLL_CHEST] = p->readUInt(); // PAPERDOLL_CHEST
paperdoll_augid[L2_PAPERDOLL_LEGS] = p->readUInt(); // PAPERDOLL_LEGS
paperdoll_augid[L2_PAPERDOLL_FEET] = p->readUInt(); // PAPERDOLL_FEET
paperdoll_augid[L2_PAPERDOLL_BACK] = p->readUInt(); // PAPERDOLL_BACK
paperdoll_augid[L2_PAPERDOLL_LRHAND] = p->readUInt(); // PAPERDOLL_LRHAND
paperdoll_augid[L2_PAPERDOLL_HAIR] = p->readUInt(); // PAPERDOLL_HAIR
paperdoll_augid[L2_PAPERDOLL_HAIR2] = p->readUInt(); // PAPERDOLL_HAIR2
// kamael
paperdoll_augid[L2_PAPERDOLL_RBRACELET] = p->readUInt(); // PAPERDOLL_RBRACELET
paperdoll_augid[L2_PAPERDOLL_LBRACELET] = p->readUInt(); // PAPERDOLL_LBRACELET
paperdoll_augid[L2_PAPERDOLL_DECO1] = p->readUInt(); // PAPERDOLL_DECO1
paperdoll_augid[L2_PAPERDOLL_DECO2] = p->readUInt(); // PAPERDOLL_DECO2
paperdoll_augid[L2_PAPERDOLL_DECO3] = p->readUInt(); // PAPERDOLL_DECO3
paperdoll_augid[L2_PAPERDOLL_DECO4] = p->readUInt(); // PAPERDOLL_DECO4
paperdoll_augid[L2_PAPERDOLL_DECO5] = p->readUInt(); // PAPERDOLL_DECO5
paperdoll_augid[L2_PAPERDOLL_DECO6] = p->readUInt(); // PAPERDOLL_DECO6
//
if( l2_version >= L2_VERSION_T23 )
paperdoll_augid[L2_PAPERDOLL_BELT] = p->readUInt(); // PAPERDOLL_BELT
// Gracia Final 2.3
if( l2_version == L2_VERSION_T23 )
{
p->readD();
p->readD();
}
pvpFlag = p->readUInt(); // pvp flag
karma = p->readInt(); // karma
mAtkSpd = p->readInt(); // cast speed
pAtkSpd = p->readInt(); // atk speed
pvpFlag = p->readUInt(); // pvp flag
karma = p->readInt(); // karma
runSpeed = p->readInt(); // run spd
walkSpeed = p->readInt(); // walk spd
p->readInt(); // _swimRunSpd (?)
p->readInt(); // _swimWalkSpd (?)
p->readInt(); // _flRunSpd (?)
p->readInt(); // _flWalkSpd (?)
p->readInt(); // _flyRunSpd (?)
p->readInt(); // _flyWalkSpd (?)
double moveMult = p->readDouble(); // move spd mult
double atkMult = p->readDouble(); // atk spd mult
// apply multipliers
if( moveMult > 0 )
{
runSpeed = (int)( ((double)(runSpeed)) * moveMult );
walkSpeed = (int)( ((double)(walkSpeed)) * moveMult );
}
if( atkMult > 0 ) pAtkSpd = (int)( ((double)(pAtkSpd)) * atkMult );
collisionRadius = p->readF(); // collisionRadius
collisionHeight = p->readF(); // collisionHeight
hairStyle = p->readInt();
hairColor = p->readInt();
face = p->readInt();
setTitle( p->readUnicodeStringPtr() ); // title
clanID = p->readUInt();
clanCrestID = p->readInt();
allyID = p->readInt();
allyCrestID = p->readInt();
p->readInt(); // relation(?), which is always 0
isSitting = (int)(!p->readUChar()); // standing = 1 sitting = 0
isRunning = (int)p->readUChar(); // running = 1 walking = 0
isInCombat = (int)p->readUChar();
isAlikeDead = (int)p->readUChar();
p->readUChar(); // invisible = 1 visible =0
this->mountType = p->readUChar(); // 1-on Strider, 2-on Wyvern, 3-on Great Wolf, 0-no mount
this->privateStoreType = p->readUChar(); // 1 - sellshop
// cubics
numCubics = (int)p->readUShort(); // cubics count
if( numCubics > 4 ) numCubics = 4;
for( i=0; i<numCubics; i++ )
cubicId[i] = (unsigned int)p->readUShort(); // cubic ID
p->readUChar(); // find party members
abnormalEffect = p->readUInt(); // abnormalEffect
recomLeft = (int)p->readUChar();
recomHave = (int)p->readUShort(); // Blue value for name (0 = white, 255 = pure blue)
mountNpcId = p->readUInt() - 1000000; // mountNpcId + 1000000
classID = p->readUInt(); // class ID
p->readUInt(); // 0x00
enchantEffect = (unsigned int)p->readUChar();
p->readUChar(); // team circle around feet 1 = Blue, 2 = red
clanCrestLargeID = p->readUInt();
isNoble = p->readUChar();
isHero = p->readUChar(); // hero aura
isFishing = p->readUChar(); // 0x01: Fishing Mode (Cant be undone by setting back to 0)
fishX = p->readInt();
fishY = p->readInt();
fishZ = p->readInt();
nameColor = p->readInt();
heading = p->readUInt();
pledgeClass = p->readUInt(); // PledgeClass
pledgeType = p->readUInt(); // PledgeType
titleColor = p->readUInt(); // TitleColor
cursedWeaponId = p->readUInt(); // CursedWeaponEquippedId
clanRepScore = p->readInt(); // clan ReputationScore
// T1
transformId = p->readUInt(); // TransformationId
agathionId = p->readUInt(); // AgathionId
// T2
//writeD(0x01);
// T2.3
//writeD(0x00);
//writeD(0x00);
//writeD(0x00);
//writeD(0x00);
// set last time when char coordinates were known exactly
lastMoveTickTime = OS_GetTickCount();
return true;
}
bool L2Player::parse_UserInfo( void *l2_game_packet, L2_VERSION l2_version )
{
if( !l2_game_packet ) return false;
unsigned int tempUINT;
int i;
L2GamePacket *p = (L2GamePacket *)l2_game_packet;
unsigned char ptype = p->getPacketType();
if( ptype != 0x32 ) return false;
x = p->readInt();
y = p->readInt();
z = p->readInt();
if( l2_version <= L2_VERSION_T22 ) heading = p->readUInt();
else if( l2_version >= L2_VERSION_T23 ) vehicleObjectId = p->readUInt();
objectID = p->readUInt();
setName( p->readUnicodeStringPtr() );
race = p->readInt();
sex = p->readInt();
baseClassID = p->readUInt();
level = p->readInt();
experience = p->readUInt64();
s_STR = p->readInt(); // writeD(_activeChar.getSTR());
s_DEX = p->readInt(); // writeD(_activeChar.getDEX());
s_CON = p->readInt(); // writeD(_activeChar.getCON());
s_INT = p->readInt(); // writeD(_activeChar.getINT());
s_WIT = p->readInt(); // writeD(_activeChar.getWIT());
s_MEN = p->readInt(); // writeD(_activeChar.getMEN());
maxHp = (double)p->readInt(); // writeD(_activeChar.getMaxHp());
curHp = (double)p->readInt(); // writeD((int) _activeChar.getCurrentHp());
maxMp = (double)p->readInt(); // writeD(_activeChar.getMaxMp());
curMp = (double)p->readInt(); //writeD((int) _activeChar.getCurrentMp());
skill_points = p->readUInt(); // writeD(_activeChar.getSp());
curLoad = p->readUInt(); // writeD(_activeChar.getCurrentLoad());
maxLoad = p->readUInt(); // writeD(_activeChar.getMaxLoad());
//writeD(_activeChar.getActiveWeaponItem() != null ? 0x40 : 0x20); // 0x20 no weapon, 0x40 weapon equipped
bool isWeaponEquipped = false; // why?... cannot we check weapon paperdoll objectId/itemId?
tempUINT = p->readUInt();
if( tempUINT == 0x40 ) isWeaponEquipped = true;
// paperdoll and its augments
// paperdoll objectIDs (25 items)
paperdoll_oid[L2_PAPERDOLL_UNDER] = p->readUInt(); // Inventory.PAPERDOLL_UNDER));
paperdoll_oid[L2_PAPERDOLL_REAR] = p->readUInt(); // writeD(....PAPERDOLL_REAR));
paperdoll_oid[L2_PAPERDOLL_LEAR] = p->readUInt(); // writeD(....PAPERDOLL_LEAR));
paperdoll_oid[L2_PAPERDOLL_NECK] = p->readUInt(); // writeD(....PAPERDOLL_NECK));
paperdoll_oid[L2_PAPERDOLL_RFINGER] = p->readUInt(); // writeD(....PAPERDOLL_RFINGER));
paperdoll_oid[L2_PAPERDOLL_LFINGER] = p->readUInt(); // writeD(....PAPERDOLL_LFINGER));
paperdoll_oid[L2_PAPERDOLL_HEAD] = p->readUInt(); // writeD(....PAPERDOLL_HEAD));
paperdoll_oid[L2_PAPERDOLL_RHAND] = p->readUInt(); // writeD(....PAPERDOLL_RHAND));
paperdoll_oid[L2_PAPERDOLL_LHAND] = p->readUInt(); // writeD(....PAPERDOLL_LHAND));
paperdoll_oid[L2_PAPERDOLL_GLOVES] = p->readUInt(); // writeD(....PAPERDOLL_GLOVES));
paperdoll_oid[L2_PAPERDOLL_CHEST] = p->readUInt(); // writeD(....PAPERDOLL_CHEST));
paperdoll_oid[L2_PAPERDOLL_LEGS] = p->readUInt(); // writeD(....PAPERDOLL_LEGS));
paperdoll_oid[L2_PAPERDOLL_FEET] = p->readUInt(); // writeD(....PAPERDOLL_FEET));
paperdoll_oid[L2_PAPERDOLL_BACK] = p->readUInt(); // writeD(....PAPERDOLL_BACK));
paperdoll_oid[L2_PAPERDOLL_LRHAND] = p->readUInt(); // writeD(....PAPERDOLL_LRHAND));
paperdoll_oid[L2_PAPERDOLL_HAIR] = p->readUInt(); // writeD(....PAPERDOLL_HAIR));
paperdoll_oid[L2_PAPERDOLL_HAIR2] = p->readUInt(); // writeD(....PAPERDOLL_HAIR2));
// T1 new D's
paperdoll_oid[L2_PAPERDOLL_RBRACELET] = p->readUInt(); // writeD(....PAPERDOLL_RBRACELET));
paperdoll_oid[L2_PAPERDOLL_LBRACELET] = p->readUInt(); // writeD(....PAPERDOLL_LBRACELET));
paperdoll_oid[L2_PAPERDOLL_DECO1] = p->readUInt(); // writeD(....PAPERDOLL_DECO1));
paperdoll_oid[L2_PAPERDOLL_DECO2] = p->readUInt(); // writeD(....PAPERDOLL_DECO2));
paperdoll_oid[L2_PAPERDOLL_DECO3] = p->readUInt(); // writeD(....PAPERDOLL_DECO3));
paperdoll_oid[L2_PAPERDOLL_DECO4] = p->readUInt(); // writeD(....PAPERDOLL_DECO4));
paperdoll_oid[L2_PAPERDOLL_DECO5] = p->readUInt(); // writeD(....PAPERDOLL_DECO5));
paperdoll_oid[L2_PAPERDOLL_DECO6] = p->readUInt(); // writeD(....PAPERDOLL_DECO6));
if( l2_version >= L2_VERSION_T23 )
paperdoll_oid[L2_PAPERDOLL_BELT] = p->readUInt(); // PAPERDOLL_BELT
// paperdoll itemIDs (25 items)
paperdoll_iid[L2_PAPERDOLL_UNDER] = p->readUInt(); // Inventory.PAPERDOLL_UNDER));
paperdoll_iid[L2_PAPERDOLL_REAR] = p->readUInt(); // writeD(....PAPERDOLL_REAR));
paperdoll_iid[L2_PAPERDOLL_LEAR] = p->readUInt(); // writeD(....PAPERDOLL_LEAR));
paperdoll_iid[L2_PAPERDOLL_NECK] = p->readUInt(); // writeD(....PAPERDOLL_NECK));
paperdoll_iid[L2_PAPERDOLL_RFINGER] = p->readUInt(); // writeD(....PAPERDOLL_RFINGER));
paperdoll_iid[L2_PAPERDOLL_LFINGER] = p->readUInt(); // writeD(....PAPERDOLL_LFINGER));
paperdoll_iid[L2_PAPERDOLL_HEAD] = p->readUInt(); // writeD(....PAPERDOLL_HEAD));
paperdoll_iid[L2_PAPERDOLL_RHAND] = p->readUInt(); // writeD(....PAPERDOLL_RHAND));
paperdoll_iid[L2_PAPERDOLL_LHAND] = p->readUInt(); // writeD(....PAPERDOLL_LHAND));
paperdoll_iid[L2_PAPERDOLL_GLOVES] = p->readUInt(); // writeD(....PAPERDOLL_GLOVES));
paperdoll_iid[L2_PAPERDOLL_CHEST] = p->readUInt(); // writeD(....PAPERDOLL_CHEST));
paperdoll_iid[L2_PAPERDOLL_LEGS] = p->readUInt(); // writeD(....PAPERDOLL_LEGS));
paperdoll_iid[L2_PAPERDOLL_FEET] = p->readUInt(); // writeD(....PAPERDOLL_FEET));
paperdoll_iid[L2_PAPERDOLL_BACK] = p->readUInt(); // writeD(....PAPERDOLL_BACK));
paperdoll_iid[L2_PAPERDOLL_LRHAND] = p->readUInt(); // writeD(....PAPERDOLL_LRHAND));
paperdoll_iid[L2_PAPERDOLL_HAIR] = p->readUInt(); // writeD(....PAPERDOLL_HAIR));
paperdoll_iid[L2_PAPERDOLL_HAIR2] = p->readUInt(); // writeD(....PAPERDOLL_HAIR2));
// T1 new D's
paperdoll_iid[L2_PAPERDOLL_RBRACELET] = p->readUInt(); // writeD(....PAPERDOLL_RBRACELET));
paperdoll_iid[L2_PAPERDOLL_LBRACELET] = p->readUInt(); // writeD(....PAPERDOLL_LBRACELET));
paperdoll_iid[L2_PAPERDOLL_DECO1] = p->readUInt(); // writeD(....PAPERDOLL_DECO1));
paperdoll_iid[L2_PAPERDOLL_DECO2] = p->readUInt(); // writeD(....PAPERDOLL_DECO2));
paperdoll_iid[L2_PAPERDOLL_DECO3] = p->readUInt(); // writeD(....PAPERDOLL_DECO3));
paperdoll_iid[L2_PAPERDOLL_DECO4] = p->readUInt(); // writeD(....PAPERDOLL_DECO4));
paperdoll_iid[L2_PAPERDOLL_DECO5] = p->readUInt(); // writeD(....PAPERDOLL_DECO5));
paperdoll_iid[L2_PAPERDOLL_DECO6] = p->readUInt(); // writeD(....PAPERDOLL_DECO6));
if( l2_version >= L2_VERSION_T23 )
paperdoll_iid[L2_PAPERDOLL_BELT] = p->readUInt(); // PAPERDOLL_BELT
// paperdoll augmentation IDs (25 items)
//for( i=0; i<25; i++ ) p->readUInt();
paperdoll_augid[L2_PAPERDOLL_UNDER] = p->readUInt(); // Inventory.PAPERDOLL_UNDER));
paperdoll_augid[L2_PAPERDOLL_REAR] = p->readUInt(); // writeD(....PAPERDOLL_REAR));
paperdoll_augid[L2_PAPERDOLL_LEAR] = p->readUInt(); // writeD(....PAPERDOLL_LEAR));
paperdoll_augid[L2_PAPERDOLL_NECK] = p->readUInt(); // writeD(....PAPERDOLL_NECK));
paperdoll_augid[L2_PAPERDOLL_RFINGER] = p->readUInt(); // writeD(....PAPERDOLL_RFINGER));
paperdoll_augid[L2_PAPERDOLL_LFINGER] = p->readUInt(); // writeD(....PAPERDOLL_LFINGER));
paperdoll_augid[L2_PAPERDOLL_HEAD] = p->readUInt(); // writeD(....PAPERDOLL_HEAD));
paperdoll_augid[L2_PAPERDOLL_RHAND] = p->readUInt(); // writeD(....PAPERDOLL_RHAND));
paperdoll_augid[L2_PAPERDOLL_LHAND] = p->readUInt(); // writeD(....PAPERDOLL_LHAND));
paperdoll_augid[L2_PAPERDOLL_GLOVES] = p->readUInt(); // writeD(....PAPERDOLL_GLOVES));
paperdoll_augid[L2_PAPERDOLL_CHEST] = p->readUInt(); // writeD(....PAPERDOLL_CHEST));
paperdoll_augid[L2_PAPERDOLL_LEGS] = p->readUInt(); // writeD(....PAPERDOLL_LEGS));
paperdoll_augid[L2_PAPERDOLL_FEET] = p->readUInt(); // writeD(....PAPERDOLL_FEET));
paperdoll_augid[L2_PAPERDOLL_BACK] = p->readUInt(); // writeD(....PAPERDOLL_BACK));
paperdoll_augid[L2_PAPERDOLL_LRHAND] = p->readUInt(); // writeD(....PAPERDOLL_LRHAND));
paperdoll_augid[L2_PAPERDOLL_HAIR] = p->readUInt(); // writeD(....PAPERDOLL_HAIR));
paperdoll_augid[L2_PAPERDOLL_HAIR2] = p->readUInt(); // writeD(....PAPERDOLL_HAIR2));
// T1 new D's
paperdoll_augid[L2_PAPERDOLL_RBRACELET] = p->readUInt(); // writeD(....PAPERDOLL_RBRACELET));
paperdoll_augid[L2_PAPERDOLL_LBRACELET] = p->readUInt(); // writeD(....PAPERDOLL_LBRACELET));
paperdoll_augid[L2_PAPERDOLL_DECO1] = p->readUInt(); // writeD(....PAPERDOLL_DECO1));
paperdoll_augid[L2_PAPERDOLL_DECO2] = p->readUInt(); // writeD(....PAPERDOLL_DECO2));
paperdoll_augid[L2_PAPERDOLL_DECO3] = p->readUInt(); // writeD(....PAPERDOLL_DECO3));
paperdoll_augid[L2_PAPERDOLL_DECO4] = p->readUInt(); // writeD(....PAPERDOLL_DECO4));
paperdoll_augid[L2_PAPERDOLL_DECO5] = p->readUInt(); // writeD(....PAPERDOLL_DECO5));
paperdoll_augid[L2_PAPERDOLL_DECO6] = p->readUInt(); // writeD(....PAPERDOLL_DECO6));
if( l2_version >= L2_VERSION_T23 )
paperdoll_augid[L2_PAPERDOLL_BELT] = p->readUInt(); // PAPERDOLL_BELT
// T2.3 some 2 Ds
if( l2_version >= L2_VERSION_T23 )
{
p->readD();
p->readD();
}
pAtk = p->readInt(); // writeD(_activeChar.getPAtk(null));
pAtkSpd = p->readInt(); // writeD(_activeChar.getPAtkSpd());
pDef = p->readInt(); // writeD(_activeChar.getPDef(null));
evasion = p->readInt(); // writeD(_activeChar.getEvasionRate(null));
accuracy = p->readInt(); // writeD(_activeChar.getAccuracy());
critical = p->readInt(); // writeD(_activeChar.getCriticalHit(null, null));
mAtk = p->readInt(); // writeD(_activeChar.getMAtk(null, null));
mAtkSpd = p->readInt(); // writeD(_activeChar.getMAtkSpd());
pAtkSpd = p->readInt(); // writeD(_activeChar.getPAtkSpd());
mDef = p->readInt(); // writeD(_activeChar.getMDef(null, null));
pvpFlag = p->readInt(); // writeD(_activeChar.getPvpFlag()); // 0-non-pvp 1-pvp = violett name
karma = p->readInt(); // writeD(_activeChar.getKarma());
runSpeed = p->readInt(); // writeD(_runSpd);
walkSpeed = p->readInt(); // writeD(_walkSpd);
p->readInt(); // writeD(_swimRunSpd); // swimspeed
p->readInt(); // writeD(_swimWalkSpd); // swimspeed
p->readInt(); // writeD(_flRunSpd);
p->readInt(); // writeD(_flWalkSpd);
p->readInt(); // writeD(_flyRunSpd);
p->readInt(); // writeD(_flyWalkSpd);
double moveMultiplier = p->readDouble(); // writeF(_moveMultiplier);
double attackSpeedMultiplier = p->readDouble(); // writeF(_activeChar.getAttackSpeedMultiplier());
if( moveMultiplier > 0.0 )
{
runSpeed = (int)( ((double)(runSpeed)) * moveMultiplier + 0.5 );
walkSpeed = (int)( ((double)(walkSpeed)) * moveMultiplier + 0.5 );
}
if( attackSpeedMultiplier > 0.0 )
{
pAtkSpd = (int)( ((double)(pAtkSpd)) * attackSpeedMultiplier);
}
collisionRadius = p->readDouble(); // writeF(_activeChar.getBaseTemplate().collisionRadius);
collisionHeight = p->readDouble(); // writeF(_activeChar.getBaseTemplate().collisionHeight);
hairStyle = p->readInt(); // writeD(_activeChar.getAppearance().getHairStyle());
hairColor = p->readInt(); // writeD(_activeChar.getAppearance().getHairColor());
face = p->readInt(); // writeD(_activeChar.getAppearance().getFace());
/*isGm =*/ p->readInt(); // writeD(_activeChar.isGM() ? 1 : 0); // builder level
setTitle( p->readS() ); // writeS(title);
clanID = p->readUInt(); // writeD(_activeChar.getClanId());
clanCrestID = p->readUInt(); // writeD(_activeChar.getClanCrestId());
allyID = p->readUInt(); // writeD(_activeChar.getAllyId());
allyCrestID = p->readUInt(); // writeD(_activeChar.getAllyCrestId()); // ally crest id
// 0x40 leader rights
// siege flags: attacker - 0x180 sword over name, defender - 0x80 shield, 0xC0 crown (|leader), 0x1C0 flag (|leader)
relation = p->readUInt(); // writeD(_relation);
mountType = p->readUChar(); // writeC(_activeChar.getMountType()); // mount type
privateStoreType = (int)p->readUChar(); // writeC(_activeChar.getPrivateStoreType());
hasDwarvenCraft = p->readUChar(); // writeC(_activeChar.hasDwarvenCraft() ? 1 : 0);
pkKills = p->readInt(); // writeD(_activeChar.getPkKills());
pvpKills = p->readInt(); // writeD(_activeChar.getPvpKills());
numCubics = p->readUShort(); // writeH(_activeChar.getCubics().size());
if( numCubics > 4 ) numCubics = 4; // safe
for( i=0; i<numCubics; i++ )
cubicId[i] = p->readUShort(); //for (int id : _activeChar.getCubics().keySet()) writeH(id);
p->readUChar(); // writeC(0x00); //1-find party members
abnormalEffect = p->readUInt(); // writeD(_activeChar.getAbnormalEffect());
p->readChar(); // writeC(0x00);
clanPrivs = p->readUInt(); // writeD(_activeChar.getClanPrivileges());
recomLeft = p->readUShort(); // writeH(_activeChar.getRecomLeft());
recomHave = p->readUShort(); // writeH(_activeChar.getRecomHave());
mountNpcId = p->readUInt(); // writeD(_activeChar.getMountNpcId() + 1000000);
inventoryLimit = p->readUShort(); // writeH(_activeChar.getInventoryLimit());
classID = p->readUInt(); // writeD(_activeChar.getClassId().getId());
p->readUInt(); // writeD(0x00); // special effects? circles around player...
maxCp = (double)p->readInt(); // writeD(_activeChar.getMaxCp());
curCp = (double)p->readInt(); // writeD((int) _activeChar.getCurrentCp());
enchantEffect = p->readUChar(); // writeC(_activeChar.getEnchantEffect());
p->readUChar(); // writeC(0x00); //team circle around feet 1= Blue, 2 = red
clanCrestLargeID = p->readUInt(); // writeD(_activeChar.getClanCrestLargeId());
isNoble = p->readUChar(); // writeC(_activeChar.isNoble() ? 1 : 0);
isHero = p->readUChar(); // writeC(_activeChar.isHero()
isFishing = p->readUChar(); // writeC(_activeChar.isFishing() ? 1 : 0); //Fishing Mode
fishX = p->readUInt(); // writeD(_activeChar.getFishx()); //fishing x
fishY = p->readUInt(); // writeD(_activeChar.getFishy()); //fishing y
fishZ = p->readUInt(); // writeD(_activeChar.getFishz()); //fishing z
nameColor = p->readUInt(); // writeD(_activeChar.getAppearance().getNameColor());
//new c5
isRunning = (int)p->readUChar(); // writeC(_activeChar.isRunning() ? 0x01 : 0x00); //changes the Speed display on Status Window
pledgeClass = p->readUInt(); // writeD(_activeChar.getPledgeClass()); //changes the text above CP on Status Window
pledgeType = p->readUInt(); // writeD(_activeChar.getPledgeType());
titleColor = p->readUInt(); // writeD(_activeChar.getAppearance().getTitleColor());
// writeD(CursedWeaponsManager.getInstance().getLevel(_activeChar.getCursedWeaponEquippedId()));
cursedWeaponId = p->readUInt(); // cursedWeapon
// T1 Starts
transformId = p->readUInt(); // writeD(_activeChar.getTransformationId());
if( l2_version < L2_VERSION_T23 )
{
elements.attackElementType = p->readD(); // writeD(_activeChar.getAttackElement());
elements.attackElementValue = p->readD(); // writeD(_activeChar.getAttackElementValue());
elements.defAttrFire = p->readD(); // writeD(_activeChar.getDefAttrFire());
elements.defAttrWater = p->readD(); // writeD(_activeChar.getDefAttrWater());
elements.defAttrWind = p->readD(); // writeD(_activeChar.getDefAttrWind());
elements.defAttrEarth = p->readD(); // writeD(_activeChar.getDefAttrEarth());
elements.defAttrHoly = p->readD(); // writeD(_activeChar.getDefAttrHoly());
elements.defAttrUnholy = p->readD(); // writeD(_activeChar.getDefAttrUnholy());
}
else
{
elements.attackElementType = p->readH(); // writeH(attackAttribute);
elements.attackElementValue = p->readH(); // writeH(_activeChar.getAttackElementValue(attackAttribute));
elements.defAttrFire = p->readH(); // writeH(_activeChar.getDefenseElementValue(Elementals.FIRE));
elements.defAttrWater = p->readH(); // writeH(_activeChar.getDefenseElementValue(Elementals.WATER));
elements.defAttrWind = p->readH(); // writeH(_activeChar.getDefenseElementValue(Elementals.WIND));
elements.defAttrEarth = p->readH(); // writeH(_activeChar.getDefenseElementValue(Elementals.EARTH));
elements.defAttrHoly = p->readH(); // writeH(_activeChar.getDefenseElementValue(Elementals.HOLY));
elements.defAttrUnholy = p->readH(); // writeH(_activeChar.getDefenseElementValue(Elementals.DARK));
}
agathionId = p->readUInt(); // writeD(_activeChar.getAgathionId());
// T2
if( l2_version >= L2_VERSION_T2 )
{
fame = p->readUInt(); // writeD(_activeChar.getFame()); // Fame
p->readUInt(); // writeD(0x00); // Unknown // 0x01 in CT2.3
vitalityLevel = p->readUInt(); // writeD(_activeChar.getVitalityLevel()); // Vitality Level
}
// T2.3
//if( l2_version >= L2_VERSION_T23 )
//{
//writeD(0x00); // CT2.3
//writeD(0x00); // CT2.3
//writeD(0x00); // CT2.3
//writeD(0x00); // CT2.3
//}
// set last time when char coordinates were known exactly
lastMoveTickTime = OS_GetTickCount();
return true;
}

View File

@@ -0,0 +1,170 @@
#ifndef H_L2PLAYER
#define H_L2PLAYER
#include "L2Character.h"
#include "L2PlayerPaperDoll.h"
#include "L2ElementalInfo.h"
/** \class L2Player
Every L2Npc is L2Character:\n
Every L2Character is L2Object (has objectID, x, y, z)\n
Every L2Character has LEVEL!\n
Every L2Character has its charName and charTitle\n
Every L2Character has its heading\n
Every L2Character has its hairStyle, hairColor and face\n
Every L2Character has moving speed in states: running, walking\n
Every L2Character has its move destination: xDst, yDst, zDst\n
Every L2Character can calc its position based on destnation point and time passed since last calc\n
Every L2Character has its base stats: INT WIT MEN CON STR DEX\n
Every L2Character has its stats: pAtk, mAtk, ..., curHp, maxHp, ...\n
Every L2Character has abnormalEffect\n
Every L2Character has its target\n
Every L2Character can be in combat\n
Every L2Character has its collision radius and height\n
\n
Additionally:\n
Every L2Player has classID, baseClassID\n
Every L2Player has its appearance (Race, Sex, Face, Hair style, Hair color)\n
Every L2Player has enchantEffect\n
Every L2Player has its paperdoll: items equipped on it. Every paperdoll item can have augment ID\n
Every L2Player can fish: has isFishing, fishX, fishY, fishZ\n
Every L2Player can create sell shop: sell, buy, package sale, craft shop (has shop type and shop message)\n
Every L2Player can ride animals (mount NPC)\n
Every L2Player can give and receive recommendations\n
Every L2Player can be noble and hero\n
\n
Additionally, some values come from RelationChanged packet, not in CharInfo\n
Every L2Player has relation to current user\n
Every L2Player can be autoAttackable\n
\n
*/
class L2Player : public L2Character
{
public:
/** Default constructor, just calls setUnused() (zeroes all members) */
L2Player();
/** Copy constructor.
* \param other source to copy from
*/
L2Player( const L2Player& other );
/** Operator=
* \param other source to copy from
* \return reference to this object
*/
virtual const L2Player& operator=( const L2Player& other );
/** Just calls setUnused() (zeroes all members) */
virtual ~L2Player();
public:
/** Initializes object state (zeroes all members) */
virtual void setUnused();
public:
/** Converts player's race ID to displayable string
* \param out pointer to unicode string buffer to receive string
* \return out
*/
virtual void getRaceStr( wchar_t *out ) const;
/** Converts player's sex number to displayable string
* \param out pointer to unicode string buffer to receive string
* \return out
*/
virtual void getSexStr( wchar_t *out ) const;
/** Converts player's class ID to displayable string.\n
* This is current selected subclass (not base class).
* \param out pointer to unicode string buffer to receive string
* \return out
*/
virtual void getClassStr( wchar_t *out ) const;
/** Converts player's base class ID to displayable string.\n
* This is always player's base class.
* \param out pointer to unicode string buffer to receive string
* \return out
*/
virtual void getBaseClassStr( wchar_t *out ) const;
public:
// relation to current user constants
static const int RELATION_NONE = 0; ///< default value, no mean
static const int RELATION_PVP_FLAG = 0x00002; ///< pvp ???
static const int RELATION_HAS_KARMA = 0x00004; ///< karma ???
static const int RELATION_LEADER = 0x00080; ///< leader
static const int RELATION_INSIEGE = 0x00200; ///< true if in siege
static const int RELATION_ATTACKER = 0x00400; ///< true when attacker
static const int RELATION_ALLY = 0x00800; ///< blue siege icon, cannot have if red
static const int RELATION_ENEMY = 0x01000; ///< true when red icon, doesn't matter with blue
static const int RELATION_MUTUAL_WAR = 0x08000; ///< double fist (war)
static const int RELATION_1SIDED_WAR = 0x10000; ///< single fist (war)
// private store type constants
static const int PRIVATE_STORE_NONE = 0; ///< player has no private store
static const int PRIVATE_STORE_SELL = 1; ///< player is selling
static const int PRIVATE_STORE_BUY = 3; ///< player is buying
static const int PRIVATE_STORE_CRAFT = 5; ///< player is sitting in recipe shop mode
static const int PRIVATE_STORE_PACKAGESALE = 8; ///< player is in package sale mode
public:
bool parse_CharInfo( void *l2_game_packet, L2_VERSION l2_version );
bool parse_UserInfo( void *l2_game_packet, L2_VERSION l2_version );
public:
unsigned int classID; ///< current class ID, which may be subclass and may differ from base class ID
unsigned int baseClassID; ///< player's base class ID
int race; ///< race number
int sex; ///< 1 - female, 0 - male
int hairStyle;
int hairColor;
int face;
unsigned long long experience; // only from UserInfo
unsigned int skill_points; // only from UserInfo
int curLoad; // only from UserInfo
int maxLoad; // only from UserInfo
int pkKills; // only from UserInfo
int pvpKills; // only from UserInfo
unsigned int enchantEffect; ///< player's weapon enchant value
// from RelationChanged
unsigned int relation; ///< relation (siege flags and clan war flags,fists)
int autoAttackable; ///< 1, if player is auto attackable (2-sided war, for example)
unsigned int paperdoll_oid[32]; ///< array of paperdoll objectIDs (only from UserInfo)
unsigned int paperdoll_iid[32]; ///< array of paperdoll itemIDs
unsigned int paperdoll_augid[32]; ///< array of paperdoll augmentationIDs
int isFakeDeath;
int isFishing;
int fishX;
int fishY;
int fishZ;
int privateStoreType; ///< player's private store type. See PRIVATE_STORE_* constants (1 - sellshop, ...)
wchar_t privateStoreMsgBuy[64]; ///< buy shop message
wchar_t privateStoreMsgSell[64]; ///< sell shop message
wchar_t privateStoreMsgRecipe[64]; ///< recipe shop message
unsigned int mountType; ///< 1-on Strider, 2-on Wyvern, 3-on Great Wolf, 0-no mount
unsigned int mountNpcId; ///< mount NPC template ID
int recomLeft; ///< number of recommendations this player can give to others
int recomHave; ///< number of received recommendations
int isNoble; ///< 1 if is noblesse
int isHero; ///< 1 if is hero
unsigned int nameColor;
unsigned int titleColor;
unsigned int pledgeClass; ///< pledge class (TODO)
unsigned int pledgeType; ///< pledge type (TODO)
unsigned int cursedWeaponId;
int clanRepScore; ///< clan reputation score or 0, if no clan
unsigned int transformId;
unsigned int agathionId;
unsigned int vehicleObjectId; // O_o Gracia Final
int hasDwarvenCraft; // only for UserInfo
int numCubics;
unsigned int cubicId[4];
unsigned int clanPrivs; // only for UserInfo
int inventoryLimit; // only for UserInfo
L2ElementalInfo elements; // only for UserInfo
int fame; // only for UserInfo
int vitalityLevel; // only for UserInfo
};
#endif

View File

@@ -0,0 +1,42 @@
#ifndef H_L2PLAYER_PAPERDOLL_
#define H_L2PLAYER_PAPERDOLL_
/** \file L2PlayerPaperDoll.h
* Defines paperdoll items indexes in arrays:
* unsigned int L2Player::paperdoll_iid[32];
* unsigned int L2Player::paperdoll_augid[32];
*/
#define L2_PAPERDOLL_UNDER 0
#define L2_PAPERDOLL_REAR 1
#define L2_PAPERDOLL_LEAR 2
#define L2_PAPERDOLL_LREAR 3
#define L2_PAPERDOLL_NECK 4
#define L2_PAPERDOLL_LFINGER 5
#define L2_PAPERDOLL_RFINGER 6
#define L2_PAPERDOLL_LRFINGER 7
#define L2_PAPERDOLL_HEAD 8
#define L2_PAPERDOLL_RHAND 9
#define L2_PAPERDOLL_LHAND 10
#define L2_PAPERDOLL_GLOVES 11
#define L2_PAPERDOLL_CHEST 12
#define L2_PAPERDOLL_LEGS 13
#define L2_PAPERDOLL_FEET 14
#define L2_PAPERDOLL_BACK 15
#define L2_PAPERDOLL_LRHAND 16
#define L2_PAPERDOLL_FULLARMOR 17
#define L2_PAPERDOLL_HAIR 18
#define L2_PAPERDOLL_ALLDRESS 19
#define L2_PAPERDOLL_HAIR2 20
#define L2_PAPERDOLL_HAIRALL 21
#define L2_PAPERDOLL_RBRACELET 22
#define L2_PAPERDOLL_LBRACELET 23
#define L2_PAPERDOLL_DECO1 24
#define L2_PAPERDOLL_DECO2 25
#define L2_PAPERDOLL_DECO3 26
#define L2_PAPERDOLL_DECO4 27
#define L2_PAPERDOLL_DECO5 28
#define L2_PAPERDOLL_DECO6 29
#define L2_PAPERDOLL_BELT 30
#endif

View File

@@ -0,0 +1,19 @@
#ifndef L2SKILL_H_
#define L2SKILL_H_
/** \class L2Skill
* Information about skill: skill ID, skill level and active/passive type.
*/
class L2Skill
{
public:
L2Skill(): isPassive(1), id(0), level(0) {}
~L2Skill() {}
public:
int isPassive; ///< 1, if is passive; 0 otherwise
unsigned int id; ///< skill ID
unsigned int level; ///< skill level
};
#endif

View File

@@ -0,0 +1,21 @@
#ifndef H_L2WORLD
#define H_L2WORLD
/** \file L2World.h
* Just a header to include all information about Lineage2 world...
*/
#include "L2Object.h"
#include "L2Character.h"
#include "L2Npc.h"
#include "L2Player.h"
#include "L2Skill.h"
#include "L2ChatMessageTypes.h"
#include "L2PlayerPaperDoll.h"
#include "L2Experience.h"
#include "L2ElementalInfo.h"
#endif

View File

@@ -0,0 +1,387 @@
#include "stdafx.h"
#include "L2LoginPacket.h"
//#define L2LOGINP_DEBUGOUT_BLOWFISH // can be defined in L2Packets.h
L2LoginPacket::L2LoginPacket()
{
_initNull(); // static BF key is initialized there
NEW_BLOWFISH_KEY_LEN = 0;
memset( (void *)NEW_BLOWFISH_KEY, 0, sizeof(NEW_BLOWFISH_KEY) );
}
L2LoginPacket::L2LoginPacket( const unsigned char *bytes, unsigned int length )
{
_initNull(); // static BF key is initialized there
NEW_BLOWFISH_KEY_LEN = 0;
memset( (void *)NEW_BLOWFISH_KEY, 0, sizeof(NEW_BLOWFISH_KEY) );
this->setBytes( bytes, length );
}
L2LoginPacket::~L2LoginPacket()
{
_freeSelf();
}
void L2LoginPacket::_initNull()
{
L2BasePacket::_initNull();
memset( (void *)STATIC_BLOWFISH_KEY, 0, sizeof(STATIC_BLOWFISH_KEY) );
STATIC_BLOWFISH_KEY[0] = 0x6B;
STATIC_BLOWFISH_KEY[1] = 0x60;
STATIC_BLOWFISH_KEY[2] = 0xCB;
STATIC_BLOWFISH_KEY[3] = 0x5B;
STATIC_BLOWFISH_KEY[4] = 0x82;
STATIC_BLOWFISH_KEY[5] = 0xCE;
STATIC_BLOWFISH_KEY[6] = 0x90;
STATIC_BLOWFISH_KEY[7] = 0xB1;
STATIC_BLOWFISH_KEY[8] = 0xCC;
STATIC_BLOWFISH_KEY[9] = 0x2B;
STATIC_BLOWFISH_KEY[10] = 0x6C;
STATIC_BLOWFISH_KEY[11] = 0x55;
STATIC_BLOWFISH_KEY[12] = 0x6C;
STATIC_BLOWFISH_KEY[13] = 0x6C;
STATIC_BLOWFISH_KEY[14] = 0x6C;
STATIC_BLOWFISH_KEY[15] = 0x6C;
STATIC_BLOWFISH_KEY_LEN = 16;
xor_key = 0;
}
bool L2LoginPacket::decodeBlowfish( bool bUseStaticBFKey )
{
int blen = (int)getPacketSize(); // all array length
int datalen = blen - 2; // only data len, w/o 1st 2 bytes - packet size
int n8bc = datalen / 8; // 8-byte blocks count
int rest = datalen - n8bc*8; // bytes left
if( rest > 0 ) rest = 8; // do we need addition?
int newdatalen = datalen + rest; // dlina novogo u4astka dannih
int newbuflen = newdatalen + 2; // dlina novogo paketa
if( blen < 1 ) return false; // TODO: throw?
unsigned char *buf = b.getBytesPtr();
if( !buf ) return false; // TODO: throw?
// initialize Blowfish key
BF_KEY bfkey;
if( bUseStaticBFKey )
BF_set_key( &bfkey, (int)this->STATIC_BLOWFISH_KEY_LEN,
this->STATIC_BLOWFISH_KEY );
else
BF_set_key( &bfkey, (int)this->NEW_BLOWFISH_KEY_LEN,
this->NEW_BLOWFISH_KEY );
int offset = 0;
int nPasses = 0;
unsigned char *outbuf = NULL;
// we will decode to this buffer
outbuf = (unsigned char *)malloc( newbuflen );
if( !outbuf )
{
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
printf( "L2LoginPacket::decodeBlowfish(): memory error!\n" );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
return false;
}
memset( outbuf, 0, newbuflen );
outbuf[0] = buf[0]; // copy packet len
outbuf[1] = buf[1];
nPasses = 0;
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
if( bUseStaticBFKey ) printf( "L2LoginPacket::decodeBlowfish(): using STATIC BF KEY\n" );
else printf( "L2LoginPacket::decodeBlowfish(): using DYNAMIC BF KEY\n" );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
for( offset=2; offset<newdatalen; offset+=8 )
{
unsigned char data[8] = {0,0,0,0,0,0,0,0};
memcpy( data, buf+offset, 8 );
BF_decrypt( (BF_LONG *)data, &bfkey );
memcpy( outbuf+offset, data, 8 );
nPasses++;
}
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
printf( "L2LoginPacket::decodeBlowfish(): Decode2: %d passes, %d 8-byte blocks\n", nPasses, n8bc );
//L2LoginPacket *dec2 = new L2LoginPacket( outbuf, blen );
//dec2->dumpToFile( stdout );
//dec2->saveToFileRaw( "pdecodedbf.dat" );
//delete dec2;
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
this->setBytes( outbuf, blen );
free( outbuf );
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
printf( "L2LoginPacket::decodeBlowfish(): decode complete\n" );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
return true;
}
bool L2LoginPacket::setDynamicBFKey( unsigned char *newKey, unsigned int newKeyLen )
{
if( !newKey ) return false;
if( newKeyLen < 1 ) return false;
memcpy( this->NEW_BLOWFISH_KEY, newKey, newKeyLen );
this->NEW_BLOWFISH_KEY_LEN = newKeyLen;
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
printf( "L2LoginPacket::setDynamicBFKey(): set dynamic BF key of len = %u\n",
newKeyLen );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
return true;
}
bool L2LoginPacket::decodeBlowfish( unsigned char *blowfishKey )
{
setDynamicBFKey( blowfishKey, 16 );
return decodeBlowfish( false );
}
/*bool L2LoginPacket::appendChecksum()
{
// save packet len bytes
//unsigned char plenbytes[2] = {0,0}
//plenbytes[0] = b.getByteAt( 0 );
//plenbytes[1] = b.getByteAt( 1 );
// get packet length
unsigned int count = this->getPacketSize();
if( count > 2 )
{
unsigned char *rawbytes = b.getBytesPtr();
unsigned int chksum = 0;
unsigned int i = 0;
for( i=2; i<count; i += 4 ) chksum ^= *( (unsigned int *)&rawbytes[i] );
this->writeUInt( chksum );
// restore plen bytes
//b.setByteAt( 0, plenbytes[0] );
//b.setByteAt( 1, plenbytes[1] );
return true;
}
return false;
}*/
bool L2LoginPacket::appendChecksum( bool append4bytes )
{
unsigned char *raw = b.getBytesPtr();
int size = (int)this->real_size;
unsigned int chksum = 0;
int count = size; // size-4; // we do not reserve space for checksum
unsigned int ecx = 0;
int i = 0;
int offset = 2;
#ifdef L2LOGINP_DEBUGOUT_CHKSUM
printf( "L2LoginPacket::appendChecksum(): for( i=%d; i<%d; i+=4)\n",
offset, count );
#endif // L2LOGINP_DEBUGOUT_CHKSUM
for( i = offset; i<count; i+=4 )
{
ecx = (raw[i]) & 0x000000ff;
ecx |= (raw[i+1] << 0x08) & 0x0000ff00;
ecx |= (raw[i+2] << 0x10) & 0x00ff0000;
ecx |= (raw[i+3] << 0x18) & 0xff000000;
chksum ^= ecx;
}
ecx = raw[i] & 0x000000ff;
ecx |= raw[i+1] << 0x08 & 0x0000ff00;
ecx |= raw[i+2] << 0x10 & 0x00ff0000;
ecx |= raw[i+3] << 0x18 & 0xff000000;
// write chksum to end of packet
/*/// L2J style :)
raw[i] = (unsigned char)((chksum) & 0xff);
raw[i+1] = (unsigned char)((chksum >> 0x08) & 0xff);
raw[i+2] = (unsigned char)((chksum >> 0x10) & 0xff);
raw[i+3] = (unsigned char)((chksum >> 0x18) & 0xff);
*/
//this->write_ptr = i+4;
#ifdef L2LOGINP_DEBUGOUT_CHKSUM
printf( "L2LoginPacket::appendChecksum(): writing chksum [%04X] at indexes [%d..%d]\n",
chksum, this->write_ptr, this->write_ptr+3 );
#endif // L2LOGINP_DEBUGOUT_CHKSUM
writeUChar( (unsigned char)((chksum) & 0xff) );
writeUChar( (unsigned char)((chksum >> 0x08) & 0xff) );
writeUChar( (unsigned char)((chksum >> 0x10) & 0xff) );
writeUChar( (unsigned char)((chksum >> 0x18) & 0xff) );
// Should we also automatically append 4 0x00 symbols to packet?
// Before calling appendChecksum(), packet is considered to be
// aligned at 8-byte border, so adding 4 bytes of checksum
// breaks this alignment. And adding more 4 zero bytes will
// resore 8-byte border alignment.
// But sometimes this adding is not necessary, for example,
// when encoding packet from Login Server to Client.
if( append4bytes )
{
writeUChar( 0x00 );
writeUChar( 0x00 );
writeUChar( 0x00 );
writeUChar( 0x00 );
}
return true;
}
bool L2LoginPacket::verifyBytesChecksum( const unsigned char *bytes, unsigned int offset, unsigned int size )
{
if( !bytes || (size<8) ) return false;
if( size % 4 != 0 ) return false; // data size should be a multiple of 4
//
unsigned int chksum = 0;
unsigned int count = size-4;
unsigned int check = 0xFFFFFFFF;
unsigned int i = 0;
//
for( i=offset; i<count; i+=4 )
{
check = bytes[i] & 0xFF;
check |= (bytes[i+1] << 8) & 0xFF00;
check |= (bytes[i+2] << 16) & 0xFF0000;
check |= (bytes[i+3] << 24) & 0xFF000000;
chksum ^= check;
}
check = bytes[i] & 0xFF;
check |= (bytes[i+1] << 8) & 0xFF00;
check |= (bytes[i+2] << 16) & 0xFF0000;
check |= (bytes[i+3] << 24) & 0xFF000000;
//
return (check == chksum);
}
bool L2LoginPacket::verifyChecksum() const
{
const unsigned char *bytes = getBytesPtr();
unsigned int data_len = getDataSize();
return L2LoginPacket::verifyBytesChecksum( bytes, 2, data_len );
}
bool L2LoginPacket::padPacketTo8ByteLen()
{
unsigned char *packet = b.getBytesPtr();
unsigned int plen = getPacketSize();
if( !packet || plen<3 ) return false;
unsigned int datalen = plen-2;
#ifdef L2LOGINP_DEBUGOUT_PADDING
printf( "L2LoginPacket::padPacketTo8ByteLen(): len = %u (data len = %d)\n",
plen, datalen );
#endif // L2LOGINP_DEBUGOUT_PADDING
unsigned int rest = datalen % 8;
unsigned int addsize = 0;
if( rest > 0 ) addsize = 8 - rest;
#ifdef L2LOGINP_DEBUGOUT_PADDING
printf( "L2LoginPacket::padPacketTo8ByteLen(): We should add %u bytes (rest is %u)\n",
addsize, rest );
#endif // L2LOGINP_DEBUGOUT_PADDING
// save packet len bytes
//unsigned char plenbytes[2] = {0,0};
//plenbytes[0] = b.getByteAt( 0 );
//plenbytes[1] = b.getByteAt( 1 );
// append by NULLs if we must append something
if( addsize > 0 )
{
unsigned int i;
for( i=0; i<addsize; i++ ) this->writeUChar( 0x00 );
// restore plen bytes
//b.setByteAt( 0, plenbytes[0] );
//b.setByteAt( 1, plenbytes[1] );
#ifdef L2LOGINP_DEBUGOUT_PADDING
printf( "L2LoginPacket::padPacketTo8ByteLen(): "
"after padding real_size = [%u] ==== \n", this->real_size );
//this->dumpToFile( stdout );
#endif // L2LOGINP_DEBUGOUT_PADDING
}
return true;
}
bool L2LoginPacket::appendMore8Bytes()
{
int i;
for( i=0; i<8; i++ ) writeUChar( 0x00 );
return true;
}
bool L2LoginPacket::encodeBlowfish( bool bUseStaticBFKey )
{
unsigned char *buf = this->b.getBytesPtr();
if( !buf ) return false; // TODO: throw
unsigned int blen = getPacketSize();
if( blen < 1 ) return false; // TODO: throw
//unsigned int datalen = blen - 2; // C4189: local variable is initialized but not referenced
//this->padPacketTo8ByteLen(); // manually
// initialize Blowfish key
BF_KEY bfkey;
if( bUseStaticBFKey )
BF_set_key( &bfkey, (int)this->STATIC_BLOWFISH_KEY_LEN,
this->STATIC_BLOWFISH_KEY );
else
BF_set_key( &bfkey, (int)this->NEW_BLOWFISH_KEY_LEN,
this->NEW_BLOWFISH_KEY );
unsigned int offset = 0;
int nPasses = 0;
unsigned char *outbuf = NULL;
// we will decode to this buffer
outbuf = (unsigned char *)malloc( blen );
if( !outbuf )
{
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
printf( "L2LoginPacket::encodeBlowfish(): memory error!\n" );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
return false;
}
memset( outbuf, 0, blen );
outbuf[0] = buf[0]; // copy packet len
outbuf[1] = buf[1];
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
if( bUseStaticBFKey ) printf( "L2LoginPacket::encodeBlowfish(): using STATIC BF KEY\n" );
else printf( "L2LoginPacket::encodeBlowfish(): using DYNAMIC BF KEY\n" );
printf( "L2LoginPacket::encodeBlowfish(): blen = %u, datalen = %u\n",
blen, datalen );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
for( offset=2; offset<real_size-2; offset+=8 )
{
unsigned char data[8] = {0,0,0,0,0,0,0,0};
memcpy( data, buf+offset, 8 );
BF_encrypt( (BF_LONG *)data, &bfkey );
memcpy( outbuf+offset, data, 8 );
nPasses++;
}
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
int n8bc = datalen / 8;
printf( "L2LoginPacket::encodeBlowfish(): %d passes, %d 8-byte blocks ==\n",
nPasses, n8bc );
//L2LoginPacket dec2; // = new L2LoginPacket();
//printf( "here\n" );
//bool bret = dec2.setBytes( outbuf, real_size );
//if( bret ) printf( "true\n" ); else printf( "false\n" );
//dec2.dumpToFile( stdout );
//delete dec2;
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
this->setBytes( outbuf, blen );
free( outbuf );
#ifdef L2LOGINP_DEBUGOUT_BLOWFISH
printf( "L2LoginPacket::encodeBlowfish(): encode complete\n" );
#endif // L2LOGINP_DEBUGOUT_BLOWFISH
return true;
}
bool L2LoginPacket::encodeAndPrepareToSend( unsigned char *blowfishKey, unsigned int bfKeyLen /*= 16*/ )
{
if( !setDynamicBFKey( blowfishKey, bfKeyLen ) ) return false;
if( !padPacketTo8ByteLen() ) return false;
appendChecksum( true );
appendMore8Bytes();
return encodeBlowfish( false );
}

View File

@@ -0,0 +1,76 @@
#ifndef H_L2LOGINPACKET
#define H_L2LOGINPACKET
#include "../base/L2BasePacket.h"
/** \class L2LoginPacket
* A base class for all login server communication packets.
* Includes functions to handle Blowfish encryption/decryption and checksum calculations. */
class L2LoginPacket: public L2BasePacket
{
public:
/** Default constructor */
L2LoginPacket();
/** Constructs object and calls setBytes() with parameters bytes, length
* \param bytes data to set
* \param length data size */
L2LoginPacket( const unsigned char *bytes, unsigned int length );
virtual ~L2LoginPacket();
public:
/** Does Blowfish decryption of packet data.
* \param bUseStaticBFKey set to true to use static BF key, or false to dynamic.
Dynamic BF key must be set before by setDynamicBFKey()
* \return success status */
virtual bool decodeBlowfish( bool bUseStaticBFKey );
/** Does Blowfish decryption of packet data.
* \param blowfishKey - 16 bytes array, blowfish key to use to decrypt packet data
* \return success status */
virtual bool decodeBlowfish( unsigned char *blowfishKey );
public:
/** Appends checksum to packet
* \param append4bytes in Hellbound, set to true to keep packet data length 8-byte aligned */
virtual bool appendChecksum( bool append4bytes = true );
/** Verifies data checksum, XORing count bytes starting from offset.\n
* Checksum must be written at last 4 bytes of data, so data size must be >= 8 at least.
* \param bytes data array
* \param offset starting position
* \param size data size in bytes (should be a multiple of 4)
* \return true, if checksum is ok */
static bool verifyBytesChecksum( const unsigned char *bytes, unsigned int offset, unsigned int size );
/** Verifies this packet checksum. */
virtual bool verifyChecksum() const;
/** Does padding of packet data by zeroes to 8-byte border (before BF encryption) */
virtual bool padPacketTo8ByteLen();
/** In Hellbound, packets are padded by more 8 zero bytes after adding checksum & 4 bytes */
virtual bool appendMore8Bytes();
/** Sets dynamic Blowfish key (which is taken from Init packet)
* \param newKey must point at 16 bytes buffer
* \param newKeyLen currently must be = 16 */
virtual bool setDynamicBFKey( unsigned char *newKey, unsigned int newKeyLen );
/** Does Blowfish encryption.
* \param bUseStaticBFKey set to true to use static BF key, or false to dynamic.
Dynamic BF key must be set before by setDynamicBFKey()
* \return success status */
virtual bool encodeBlowfish( bool bUseStaticBFKey );
public:
/** Encrypts packet with Blowfish, does all padding, appends checksum - after that packet may be sent
* \param blowfishKey - Blowfish key to use for encryption (16 bytes)
* \param bfKeyLen - length of Blowfish key (default is 16)
* \return success status */
virtual bool encodeAndPrepareToSend( unsigned char *blowfishKey, unsigned int bfKeyLen = 16 );
protected:
/** Also initializes STATIC_BF_KEY, which is constant. */
virtual void _initNull();
protected:
unsigned char STATIC_BLOWFISH_KEY[32]; ///< Static Blowfish key (First packet from login server is encrypted by this)
unsigned int STATIC_BLOWFISH_KEY_LEN; ///< length of static BF key
unsigned char NEW_BLOWFISH_KEY[64]; ///< Buffer to hold dynamic blowfish key
unsigned int NEW_BLOWFISH_KEY_LEN; ///< Dynamic BF key size
unsigned int xor_key; ///< current XOR key (for Init packet)
};
#endif /* H_L2LOGINPACKET */

View File

@@ -0,0 +1,134 @@
#include "stdafx.h"
#include "L2Login_RequestAuthLogin.h"
L2Login_RequestAuthLogin::L2Login_RequestAuthLogin()
{
_initNull();
}
L2Login_RequestAuthLogin::L2Login_RequestAuthLogin( const unsigned char *bytes, unsigned int length )
{
_initNull();
setBytes( bytes, length );
}
// RSA_pubKeyMod must point to 128-bytes length buffer
bool L2Login_RequestAuthLogin::create( const char *szL2Login, const char *szL2Password,
unsigned int ggAuthResponse, const unsigned char *RSA_pubKeyMod )
{
// assert
if( !szL2Login || !szL2Password ) return false;
// vars
size_t l2l_len = strlen( szL2Login );
size_t l2p_len = strlen( szL2Password );
char l2login[L2_LOGIN_MAXLEN];
char l2password[L2_PASSWORD_MAXLEN];
unsigned char block128[128];
int i = 0;
const int l2l_offset = 94;
const int l2p_offset = 108;
// memsets
memset( l2login, 0, sizeof(l2login) );
memset( l2password, 0, sizeof(l2password) );
memset( block128, 0, sizeof(block128) );
// check strings length
if( (l2l_len<1) || (l2l_len>L2_LOGIN_MAXLEN) )
{
printf( "L2Login_RequestAuthLogin::create(): L2 Login length must be [1..%d] chars\n",
L2_LOGIN_MAXLEN );
return false;
}
if( (l2p_len<1) || (l2p_len>L2_PASSWORD_MAXLEN) )
{
printf( "L2Login_RequestAuthLogin::create(): L2 Password length must be [1..%d] chars\n",
L2_PASSWORD_MAXLEN );
return false;
}
// copy strings
for( i=0; i<(int)l2l_len; i++ ) l2login[i] = szL2Login[i];
for( i=0; i<(int)l2p_len; i++ ) l2password[i] = szL2Password[i];
// copy login/pass to 128-byte block
memcpy( (void *)(block128 + l2l_offset), l2login, L2_LOGIN_MAXLEN );
memcpy( (void *)(block128 + l2p_offset), l2password, L2_PASSWORD_MAXLEN );
// RSA encode block...
if( !this->block_encode_RSA( block128, sizeof(block128), RSA_pubKeyMod ) ) return false;
// construct packet
this->writeReset();
this->setPacketType( 0x00 ); // RequestAuthLogin code
this->writeBytes( block128, sizeof(block128) ); // block with login/password
this->writeUInt( ggAuthResponse ); // from GGAuthResponse
for( i=0; i<16; i++ ) this->writeUChar( 0x00 ); // 16 NULLs
this->writeUChar( 0x08 );
for( i=0; i<10; i++ ) this->writeUChar( 0x00 ); // some 11 bytes
// now packet must be padded to 8-byte border
// next caller must add checksum, and so on...
return true;
}
// for internal use only
// encode block with login/password
// RSA_pubKeyMod must point to 128-bytes length buffer
bool L2Login_RequestAuthLogin::block_encode_RSA( unsigned char *block , unsigned int blockSize,
const unsigned char *RSA_pubKeyMod )
{
if( !block || (blockSize<1) || !RSA_pubKeyMod ) return false;
bool retVal = true;
unsigned char blockE[128];
memset( blockE, 0, sizeof(blockE) );
// allocate & initialize RSA struct
RSA *rsa = RSA_new();
// set exponent and n
rsa->e = BN_new();
BN_dec2bn( &(rsa->e), "65537" ); // exponent is constant, 65537
rsa->n = BN_bin2bn( RSA_pubKeyMod, 128, NULL ); // n is taken from unscrambled RSA public key modulus from Init packet
//printf( "RSA_size: %d\n", RSA_size( rsa ) );
int res = RSA_public_encrypt( 128, block, blockE, rsa, RSA_NO_PADDING );
if( res == -1 )
{
retVal = false;
fprintf( stderr, "RSA_public_encrypt res: %d\n", res );
ERR_print_errors_fp( stderr );
}
// store result...
memcpy( block, blockE, 128 );
// free RSA struct
RSA_free( rsa );
rsa = NULL;
return retVal;
}
bool L2Login_RequestAuthLogin::block_decode_RSA( unsigned char *block , unsigned int blockSize,
const unsigned char *RSA_pubKeyMod )
{
if( !block || (blockSize<1) || !RSA_pubKeyMod ) return false;
bool retVal = true;
unsigned char blockE[128];
memset( blockE, 0, sizeof(blockE) );
// allocate & initialize RSA struct
RSA *rsa = RSA_new();
// set exponent and n
rsa->e = BN_new();
BN_dec2bn( &(rsa->e), "65537" ); // exponent is constant, 65537
rsa->n = BN_bin2bn( RSA_pubKeyMod, 128, NULL ); // n is taken from unscrambled RSA public key modulus from Init packet
int res = RSA_private_decrypt( 128, block, blockE, rsa, RSA_NO_PADDING );
if( res == -1 )
{
retVal = false;
fprintf( stderr, "RSA_private_decrypt res: %d\n", res );
ERR_print_errors_fp( stderr );
}
// store result...
memcpy( block, blockE, 128 );
// free RSA struct
RSA_free( rsa );
rsa = NULL;
return retVal;
}
bool L2Login_RequestAuthLogin::parse( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
fprintf( stderr, "L2Login_RequestAuthLogin::parse() not implemented!\n" );
return false;
}

View File

@@ -0,0 +1,36 @@
#ifndef L2LOGIN_REQUESTAUTHLOGIN_H_
#define L2LOGIN_REQUESTAUTHLOGIN_H_
#include "../L2LoginPacket.h"
#define L2_LOGIN_MAXLEN 14
#define L2_PASSWORD_MAXLEN 16
class L2Login_RequestAuthLogin: public L2LoginPacket
{
public:
L2Login_RequestAuthLogin();
L2Login_RequestAuthLogin( const unsigned char *bytes, unsigned int length );
public:
// RSA_pubKeyMod must point to 128-bytes length buffer
bool create( const char *szL2Login, const char *szL2Password,
unsigned int ggAuthResponse, const unsigned char *RSA_pubKeyMod );
//virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
public:
char strLogin[32];
char strPassword[32];
unsigned int uGGAuthResponse;
protected:
// for internal use only
// encode block with login/password
// RSA_pubKeyMod must point to 128-bytes length buffer
bool block_encode_RSA( unsigned char *block , unsigned int blockSize,
const unsigned char *RSA_pubKeyMod );
bool block_decode_RSA( unsigned char *block , unsigned int blockSize,
const unsigned char *RSA_pubKeyMod );
};
#endif /*L2LOGIN_REQUESTAUTHLOGIN_H_*/

View File

@@ -0,0 +1,43 @@
#include "stdafx.h"
#include "L2Login_RequestGGAuth.h"
L2Login_RequestGGAuth::L2Login_RequestGGAuth()
{
this->_initNull();
sessionId[0] = sessionId[1] = sessionId[2] = sessionId[3] = 0;
}
L2Login_RequestGGAuth::L2Login_RequestGGAuth( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
sessionId[0] = sessionId[1] = sessionId[2] = sessionId[3] = 0;
}
// sesionID - 4 bytes array
bool L2Login_RequestGGAuth::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
// set packet type
this->setPacketType( 0x07 );
// write sessionID
this->writeUChar( sessionId[0] );
this->writeUChar( sessionId[1] );
this->writeUChar( sessionId[2] );
this->writeUChar( sessionId[3] );
// write 16 0x00
int i;
for( i=0; i<16; i++ ) this->writeUChar( 0x00 );
return true;
}
bool L2Login_RequestGGAuth::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x07 ) return false;
sessionId[0] = readUChar();
sessionId[1] = readUChar();
sessionId[2] = readUChar();
sessionId[3] = readUChar();
return true;
}

View File

@@ -0,0 +1,19 @@
#ifndef LOGIN_REQUESTGGAUTH_H_
#define LOGIN_REQUESTGGAUTH_H_
#include "../L2LoginPacket.h"
class L2Login_RequestGGAuth: public L2LoginPacket
{
public:
L2Login_RequestGGAuth();
L2Login_RequestGGAuth( const unsigned char *bytes, unsigned int length );
public:
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned char sessionId[4];
};
#endif /*LOGIN_REQUESTGGAUTH_H_*/

View File

@@ -0,0 +1,34 @@
#include "stdafx.h"
#include "L2Login_RequestServerList.h"
/*
22 00 // packet size - 34 bytes
05 // packet type - RequestServerList
e0 43 ef 46 8e dc 83 f2 // sessionKey #1
04 00 00 00 00 00 00 // some 7 bytes
b1 6a 9f 6c 00 00 00 00 // checksum and 4 0x00 bytes of checksum padding
00 00 00 00 00 00 00 00 // 8 0x00 bytes padding
*/
L2Login_RequestServerList::L2Login_RequestServerList()
{
this->_initNull();
}
L2Login_RequestServerList::L2Login_RequestServerList( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
bool L2Login_RequestServerList::create( const unsigned char *sessionKey1 )
{
if( !sessionKey1 ) return false;
this->writeReset();
this->setPacketType( 0x05 );
this->writeBytes( sessionKey1, 8 );
unsigned char somebytes[7] = { 4,0,0,0, 0,0,0 };
this->writeBytes( somebytes, sizeof(somebytes) );
// now packet is padded at 8-byte border. all left to is add checksum
return true;
}

View File

@@ -0,0 +1,25 @@
#ifndef L2LOGIN_REQUESTSERVERLIST_H_
#define L2LOGIN_REQUESTSERVERLIST_H_
#include "../L2LoginPacket.h"
/*
22 00 // packet size - 34 bytes
05 // packet type - RequestServerList
e0 43 ef 46 8e dc 83 f2 // sessionKey #1
04 00 00 00 00 00 00 // some 7 bytes
b1 6a 9f 6c 00 00 00 00 // checksum and 4 0x00 bytes of checksum padding
00 00 00 00 00 00 00 00 // 8 0x00 bytes padding
*/
class L2Login_RequestServerList : public L2LoginPacket
{
public:
L2Login_RequestServerList();
L2Login_RequestServerList( const unsigned char *bytes, unsigned int length );
public:
// sessionKey1 - 8-byte array (from LoginOK packet)
bool create( const unsigned char *sessionKey1 );
};
#endif /*L2LOGIN_REQUESTSERVERLIST_H_*/

View File

@@ -0,0 +1,70 @@
#include "stdafx.h"
#include "L2Login_RequestServerLogin.h"
/**
* Format is ddc
* d: first part of session id
* d: second part of session id
* c: server ID
*/
L2Login_RequestServerLogin::L2Login_RequestServerLogin()
{
this->_initNull();
}
L2Login_RequestServerLogin::L2Login_RequestServerLogin( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
// sessionKey1 must point to 8-byte array
// this is Session Key #1 from LoginOK packet
bool L2Login_RequestServerLogin::create( const unsigned char *sessionKey1,
unsigned char GameServerID )
{
if( !sessionKey1 || (GameServerID == 0x00) ) return false;
// construct packet
this->writeReset();
this->setPacketType( 0x02 ); // RequestServerLogin
this->writeBytes( sessionKey1, 8 );
this->writeUChar( GameServerID );
// pad to 8-byte border
int i;
for( i=0; i<6; i++ ) this->writeUChar( 0x00 );
return true;
}
bool L2Login_RequestServerLogin::read_sessionKey1( unsigned char *bytes )
{
if( !this->canReadBytes(8) ) return false;
return this->readBytes( bytes, 8 );
}
unsigned char L2Login_RequestServerLogin::read_GameServerID()
{
return this->readUChar();
}
bool L2Login_RequestServerLogin::parse( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x02 ) return false;
if( !canReadBytes( 9 ) ) return false;
readBytes( p_sessionKey1, 8 );
p_gameServerId = readUChar();
return true;
}
bool L2Login_RequestServerLogin::create( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x02 ); // RequestServerLogin
writeBytes( p_sessionKey1, 8 );
writeUChar( p_gameServerId );
// pad to 8-byte border
int i;
for( i=0; i<6; i++ ) writeUChar( 0x00 );
return true;
}

View File

@@ -0,0 +1,26 @@
#ifndef L2LOGIN_REQUESTSERVERLOGIN_H_
#define L2LOGIN_REQUESTSERVERLOGIN_H_
#include "../L2LoginPacket.h"
class L2Login_RequestServerLogin : public L2LoginPacket
{
public:
L2Login_RequestServerLogin();
L2Login_RequestServerLogin( const unsigned char *bytes, unsigned int length );
public:
// sessionKey1 must point to 8-byte array
// this is Session Key #1 from LoginOK packet
bool create( const unsigned char *sessionKey1, unsigned char GameServerID );
public:
bool read_sessionKey1( unsigned char *bytes );
unsigned char read_GameServerID();
public:
bool parse( L2_VERSION ver = L2_VERSION_T1 );
bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned char p_gameServerId;
unsigned char p_sessionKey1[8];
};
#endif /*L2LOGIN_REQUESTSERVERLOGIN_H_*/

View File

@@ -0,0 +1,62 @@
#include "stdafx.h"
#include "L2Login_AccountKicked.h"
/*
writeC(0x02);
writeD(_reason.getCode());
*/
L2Login_AccountKicked::L2Login_AccountKicked()
{
this->_initNull();
p_reasonCode = 0;
}
L2Login_AccountKicked::L2Login_AccountKicked( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
p_reasonCode = 0;
}
unsigned int L2Login_AccountKicked::read_reason()
{
if( !this->canReadBytes(5) ) return 0;
this->readReset();
this->readUChar();
return this->readUInt();
}
void L2Login_AccountKicked::getReasonStr( unsigned int code, char *str )
{
if( !str ) return;
strcpy( str, "REASON_UNKNOWN" );
switch( code )
{
case REASON_DATA_STEALER: strcpy( str, "REASON_DATA_STEALER" ); break;
case REASON_GENERIC_VIOLATION: strcpy( str, "REASON_GENERIC_VIOLATION" ); break;
case REASON_7_DAYS_SUSPENDED: strcpy( str, "REASON_7_DAYS_SUSPENDED" ); break;
case REASON_PERMANENTLY_BANNED: strcpy( str, "REASON_PERMANENTLY_BANNED" ); break;
}
}
void L2Login_AccountKicked::getReasonStr( char *str )
{
L2Login_AccountKicked::getReasonStr( p_reasonCode, str );
}
bool L2Login_AccountKicked::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
if( this->getPacketType() != 0x02 ) return false;
p_reasonCode = readUInt();
return true;
}
bool L2Login_AccountKicked::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x02 );
writeUInt( p_reasonCode );
return true;
}

View File

@@ -0,0 +1,28 @@
#ifndef L2LOGIN_ACCOUNTKICKED_H_
#define L2LOGIN_ACCOUNTKICKED_H_
#include "../L2LoginPacket.h"
class L2Login_AccountKicked : public L2LoginPacket
{
public:
static const unsigned int REASON_DATA_STEALER = 0x01;
static const unsigned int REASON_GENERIC_VIOLATION = 0x08;
static const unsigned int REASON_7_DAYS_SUSPENDED = 0x10;
static const unsigned int REASON_PERMANENTLY_BANNED = 0x20;
public:
L2Login_AccountKicked();
L2Login_AccountKicked( const unsigned char *bytes, unsigned int length );
public:
unsigned int read_reason();
// str must point to buffer at 32 bytes long
static void getReasonStr( unsigned int code, char *str );
void getReasonStr( char *str );
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned int p_reasonCode;
};
#endif /*L2LOGIN_ACCOUNTKICKED_H_*/

View File

@@ -0,0 +1,52 @@
#include "stdafx.h"
#include "L2Login_GGAuthResponse.h"
/* // L2J
protected void write()
{
writeC(0x0b); // packet code
writeD(_response);
writeD(0x00);
writeD(0x00);
writeD(0x00);
writeD(0x00);
}*/
L2Login_GGAuthResponse::L2Login_GGAuthResponse()
{
this->_initNull();
}
L2Login_GGAuthResponse::L2Login_GGAuthResponse( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
unsigned int L2Login_GGAuthResponse::read_Response()
{
if( !this->canReadBytes(21) ) return 0;
this->readReset();
this->getPacketType();
return this->readUInt();
}
bool L2Login_GGAuthResponse::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
p_ggAuthResponse = read_Response();
return true;
}
bool L2Login_GGAuthResponse::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
this->writeReset();
writeC( 0x0b ); // packet code
writeD( p_ggAuthResponse );
writeD( 0x00 );
writeD( 0x00 );
writeD( 0x00 );
writeD( 0x00 );
return true;
}

View File

@@ -0,0 +1,20 @@
#ifndef LOGIN_GGAUTHRESPONSE_H_
#define LOGIN_GGAUTHRESPONSE_H_
#include "../L2LoginPacket.h"
class L2Login_GGAuthResponse : public L2LoginPacket
{
public:
L2Login_GGAuthResponse();
L2Login_GGAuthResponse( const unsigned char *bytes, unsigned int length );
public:
unsigned int read_Response();
public:
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned int p_ggAuthResponse;
};
#endif /*LOGIN_GGAUTHRESPONSE_H_*/

View File

@@ -0,0 +1,300 @@
#include "stdafx.h"
#include "L2Login_Init.h"
L2Login_Init::L2Login_Init()
{
_initNull();
_initPublicMembers();
}
L2Login_Init::L2Login_Init( const unsigned char *bytes, unsigned int length )
{
_initNull();
_initPublicMembers();
this->setBytes( bytes, length );
}
bool L2Login_Init::decodeXOR()
{
unsigned int blen = getPacketSize();
unsigned char *packet = b.getBytesPtr();
if( blen < 1 || !packet ) return false; // TODO: throw?
if( blen < 186 ) return false; // TODO: throw?
// get xor key
// XOR key position to the left from End-of-packet
unsigned int xor_offset = 8;
xor_key = 0;
unsigned char b = 0;
b = packet[ blen - xor_offset ];
xor_key |= (unsigned int)b;
b = packet[ blen - xor_offset + 1 ];
xor_key |= ( (unsigned int)b << 8 );
b = packet[ blen - xor_offset + 2 ];
xor_key |= ( (unsigned int)b << 16 );
b = packet[ blen - xor_offset + 3 ];
xor_key |= ( (unsigned int)b << 24 );
// enc xor?
unsigned int offset = 2;
unsigned int edx = 0;
unsigned int ecx = xor_key;
offset = blen - xor_offset - 4;
while( offset > 2 ) // offset > 3 ?
{
edx = (packet[offset+0] & 0xFF);
edx |= (packet[offset+1] & 0xFF) << 8;
edx |= (packet[offset+2] & 0xFF) << 16;
edx |= (packet[offset+3] & 0xFF) << 24;
edx ^= ecx;
ecx -= edx;
packet[offset+0] = (unsigned char)((edx) & 0xFF);
packet[offset+1] = (unsigned char)((edx >> 8) & 0xFF);
packet[offset+2] = (unsigned char)((edx >> 16) & 0xFF);
packet[offset+3] = (unsigned char)((edx >> 24) & 0xFF);
offset -= 4;
}
return true;
}
// static function used to decrypt RSA public key modulus from Init packet
// data must be 128-byte long array
bool L2Login_Init::unscramble_RSA_PubKeyMod( unsigned char *data )
{
int i;
// step 4 xor last 0x40 bytes with first 0x40 bytes
for( i=0; i<0x40; i++ )
data[0x40 + i] = (unsigned char)(data[0x40 + i] ^ data[i]);
// step 3 xor bytes 0x0d-0x10 with bytes 0x34-0x38
for( i=0; i<4; i++ )
data[0x0d + i] = (unsigned char)(data[0x0d + i] ^ data[0x34 + i]);
// step 2 xor first 0x40 bytes with last 0x40 bytes
for( i=0; i<0x40; i++ )
data[i] = (unsigned char)(data[i] ^ data[0x40 + i]);
// step 1
for( i=0; i<4; i++ )
{
unsigned char temp = data[0x00 + i];
data[0x00 + i] = data[0x4d + i];
data[0x4d + i] = temp;
}
return true;
}
bool L2Login_Init::scramble_RSA_PubKeyMod( unsigned char *data )
{
int i;
for( i=0; i<4; i++ )
{
unsigned char temp = data[0x00 + i];
data[0x00 + i] = data[0x4d + i];
data[0x4d + i] = temp;
}
// step 2 xor first 0x40 bytes with last 0x40 bytes
for( i=0; i<0x40; i++ )
data[i] = (unsigned char)(data[i] ^ data[0x40 + i]);
// step 3 xor bytes 0x0d-0x10 with bytes 0x34-0x38
for( i=0; i<4; i++ )
data[0x0d + i] = (unsigned char)(data[0x0d + i] ^ data[0x34 + i]);
// step 4 xor last 0x40 bytes with first 0x40 bytes
for( i=0; i<0x40; i++ )
data[0x40 + i] = (unsigned char)(data[0x40 + i] ^ data[i]);
return true;
}
bool L2Login_Init::read_SessionID( unsigned char *sidBytes )
{
if( !sidBytes ) return false;
if( !canReadBytes( 4 ) ) return false;
this->readReset();
this->readChar(); // pass packet type
sidBytes[0] = this->readUChar();
sidBytes[1] = this->readUChar();
sidBytes[2] = this->readUChar();
sidBytes[3] = this->readUChar();
return true;
}
unsigned int L2Login_Init::read_ProtoVer()
{
unsigned int ret = 0;
ret = this->readUInt();
return ret;
}
// RSApublicKeyMod must point to buffer 128 bytes len
bool L2Login_Init::read_RSA_pubKeyMod( unsigned char *RSApublicKeyMod )
{
if( !RSApublicKeyMod ) return false;
if( !canReadBytes(128) ) return false;
int i = 0;
while( i < 128 ) RSApublicKeyMod[i++] = readUChar();
return true;
}
// ggShit - 16 bytes buffer; can be NULL
bool L2Login_Init::read_GGShit( unsigned char *ggShit )
{
if( !canReadBytes( 16 ) ) return false;
int i = 0;
char c = 0;
while( i < 16 )
{
c = this->readUChar();
if( ggShit ) ggShit[i] = c;
i++;
}
return true;
}
// newBFKey - 16 bytes buffer; can NOT be NULL
bool L2Login_Init::read_DynamicBFKey( unsigned char *newBFKey )
{
if( !newBFKey ) return false;
if( !canReadBytes(16) ) return false;
int i = 0;
while( i < 16 ) newBFKey[i++] = this->readUChar();
return true;
}
void L2Login_Init::displaySelfNice( FILE *f )
{
fprintf( f, "L2Login_Init: displaying self\n" );
if( this->getPacketSize() != 186 )
{
fprintf( f, "L2Login_Init: this is not standard Interlude Init packet! (wrong size)\n" );
this->dumpToFile( stdout );
return;
}
char ptype = this->getPacketType();
if( ptype != 0 )
{
fprintf( f, "L2Login_Init: this is not standard Interlude Init packet! (wrong packet type)\n" );
this->dumpToFile( stdout );
}
// vars
unsigned char sidBytes[4] = {0,0,0,0};
unsigned int protoRev = 0;
unsigned char RSA_pubKeyMod[128];
unsigned char GG_Shit[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
unsigned char dyn_BF_key[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
unsigned char nullTerm = 0;
// memsets
memset( RSA_pubKeyMod, 0, sizeof(RSA_pubKeyMod) );
// read ...
this->read_SessionID( sidBytes );
protoRev = this->read_ProtoVer();
this->read_RSA_pubKeyMod( RSA_pubKeyMod );
this->read_GGShit( GG_Shit );
this->read_DynamicBFKey( dyn_BF_key );
nullTerm = this->readUChar();
// print
int i = 0;
fprintf( f, "Packet type : Init (0)\n" );
fprintf( f, "Session ID : %02X %02X %02X %02X\n",
sidBytes[0], sidBytes[1], sidBytes[2], sidBytes[3] );
fprintf( f, "Protocol Rev : %04X\n", protoRev );
fprintf( f, "RSA pub key mod :\n" );
for( i=0; i<128; i++ ) fprintf( f, "%02X ", (unsigned int)RSA_pubKeyMod[i] );
fprintf( f, "\n" );
fprintf( f, "GG Shit : " );
for( i=0; i<16; i++ ) fprintf( f, "%02X ", (unsigned int)GG_Shit[i] );
fprintf( f, "\n" );
fprintf( f, "Dynamic BF Key : " );
for( i=0; i<16; i++ ) fprintf( f, "%02X ", (unsigned int)dyn_BF_key[i] );
fprintf( f, "\n" );
fprintf( f, "NULL terminator : %u (0x%02X)\n",
(unsigned int)nullTerm, (unsigned int)nullTerm );
fprintf( f, "Init packet dump end ;)\n\n" );
}
void L2Login_Init::_initPublicMembers()
{
p_sessionId[0] = p_sessionId[1] = p_sessionId[2] = p_sessionId[3] = 0x00;
p_protoVer = 0x00000000;
memset( p_RSA_pubKeyMod, 0, sizeof(p_RSA_pubKeyMod) );
memset( p_GG_shit, 0, sizeof(p_GG_shit) );
memset( p_BF_dyn_key, 0, sizeof(p_BF_dyn_key) );
}
bool L2Login_Init::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver); // login server packets may ignore this
//int i;
scramble_RSA_PubKeyMod( p_RSA_pubKeyMod );
// write data
writeReset();
setPacketType( 0x00 );
writeBytes( p_sessionId, 4 );
writeUInt( p_protoVer );
writeBytes( p_RSA_pubKeyMod, 128 );
writeUInt( 0x29dd954e ); // 4e 95 dd 29 // GGshit? O_o
writeUInt( 0x77c39cfc ); // fc 9c c3 77
writeUInt( 0x97adb620 ); // 20 b6 ad 97
writeUInt( 0x07bde0f7 ); // f7 e0 bd 07
writeBytes( p_BF_dyn_key, 16 );
writeChar( 0x00 );
// Init packet has no checksum or padding, but it has XOR encryption
// fill packet up to xor key position
writeD( 0x00000000 ); // write some 6 bytes, they are ignored? trash?
writeH( 0x0000 ); // tested, works OK
// now, XOR all previous bytes except first 2 bytes with packet len
// and next 4 bytes with login session id?
unsigned int xor_key = rand(); // O_o generate random XOR "key"
unsigned char *raw_bytes = b.getBytesPtr(); // we need to modify almost all bytes...
int psize = getPacketSize();
int xor_offset = 6; //2; // should we XOR login session id also?
while( xor_offset < psize )
{
// read current dword
unsigned int xoring_dword =
(unsigned int)raw_bytes[xor_offset] |
((unsigned int)raw_bytes[xor_offset+1]) << 8 |
((unsigned int)raw_bytes[xor_offset+2]) << 16 |
((unsigned int)raw_bytes[xor_offset+3]) << 24;
xor_key += xoring_dword; // increase xor key by xoring dword before XOR
xoring_dword ^= xor_key; // XOR
// decodeXOR() first XORs, then substracts :) and it goes from end of packet to beginning
// update dword inside packet
raw_bytes[xor_offset] = (unsigned char)(xoring_dword & 0xFF);
raw_bytes[xor_offset+1] = (unsigned char)(xoring_dword >> 8 & 0xFF);
raw_bytes[xor_offset+2] = (unsigned char)(xoring_dword >> 16 & 0xFF);
raw_bytes[xor_offset+3] = (unsigned char)(xoring_dword >> 24 & 0xFF);
// move to next dword
xor_offset += 4;
}
// append resulting xor key to packet
writeUInt( xor_key );
// add some 4 (trash?) bytes up to size 186
writeUInt( 0x00001234 );
// now Init packet size is 186 bytes long, all OK
// next step before sending packet to client is to encrypt Init packet
// by STATIC blowfish key (can be done by calling L2LoginPacket::encodeBlowfish( true );)
// NO need to call padPacketTo8ByteLen(), appendChecksum(), appendMore8Bytes().
return true;
}
bool L2Login_Init::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver); // login server packets may ignore this
if( getPacketSize() != 186 ) return false;
// first remove blowfish using static BF key (hardcoded)
if( !decodeBlowfish( true ) ) return false;
if( !decodeXOR() ) return false;
// read data
_initPublicMembers();
if( getPacketType() != 0x00 ) return false;
if( !read_SessionID( p_sessionId ) ) return false;
p_protoVer = read_ProtoVer();
if( !read_RSA_pubKeyMod( p_RSA_pubKeyMod ) ) return false;
if( !read_GGShit( p_GG_shit ) ) return false;
if( !read_DynamicBFKey( p_BF_dyn_key ) ) return false;
unscramble_RSA_PubKeyMod( p_RSA_pubKeyMod );
return true;
}

View File

@@ -0,0 +1,73 @@
#ifndef LOGIN_INIT_H_
#define LOGIN_INIT_H_
#include "../L2LoginPacket.h"
/**
* \class L2Login_Init
* Handles Init packet XOR encryption/decryption, RSA public key modulus scrambling/unscrambling,
* general Init packet parsing and creation.
*/
class L2Login_Init: public L2LoginPacket
{
public:
/** Default constructor */
L2Login_Init();
/** Constructs object and calls setBytes() with parameters bytes, length
* \param bytes data to set
* \param length data size */
L2Login_Init( const unsigned char *bytes, unsigned int length );
protected:
void _initPublicMembers();
public: // Init packet related encoding/decoding functions
/** Used only immediately after BF decoding */
virtual bool decodeXOR();
/** Static function used to decrypt RSA public key modulus from Init packet
* \param data must be 128-bytes array */
static bool unscramble_RSA_PubKeyMod( unsigned char *data );
/** Static function used to encrypt RSA public key modulus from Init packet
* \param data must be 128-bytes array */
static bool scramble_RSA_PubKeyMod( unsigned char *data );
public:
/** Called after decoding Init packet (removing Blowfish, XOR)
* \param sidBytes must point to array 4 bytes long */
virtual bool read_SessionID( unsigned char *sidBytes );
/** Read login protocol version (after reading sessionID) */
virtual unsigned int read_ProtoVer();
/** Read RSA public key modulus after reading login protocol version
* \param RSApublicKeyMod must point to buffer 128 bytes len */
virtual bool read_RSA_pubKeyMod( unsigned char *RSApublicKeyMod );
/** Read some 16 bytes, possibly related to GameGuard (contents and meaning unknown).
* Called after reading scrambled RSA public key modulus
* \param ggShit - 16 bytes buffer; can be NULL */
virtual bool read_GGShit( unsigned char *ggShit );
/** Read dynamic Blowfish key, which is used to encrypt/decrypt all following packets in session.
* Called after reading 16 bytes GGshit.
* \param newBFKey - 16 bytes buffer; must NOT be NULL. */
virtual bool read_DynamicBFKey( unsigned char *newBFKey );
public: // for debugging
/** Dumps Init packet to FILE line by line..
* \param f - FILE * pointer to opened file. */
virtual void displaySelfNice( FILE *f );
public: // easily create/parse Init packet using public class data members
/** Creates Init packet using public data members: p_sessionId, p_protoVer, p_RSA_pubKeyMod, p_GG_shit, p_BF_dyn_key.
* Can be used by server app. */
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
/** Parses Init packet, received from server. Result will be in public data members:
* p_sessionId, p_protoVer, p_RSA_pubKeyMod, p_GG_shit, p_BF_dyn_key.\n
* Performs BF & XOR decryption, reading data, unscrambles RSA public key modulus. */
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned char p_sessionId[4]; ///< session ID, used in some packets later in session.
unsigned int p_protoVer; ///< login server protocol version. For >= Interlude it must be 0x0000c621
unsigned char p_RSA_pubKeyMod[128]; ///< RSA public key modulus
unsigned char p_GG_shit[16]; ///< some bytes
unsigned char p_BF_dyn_key[16]; ///< dynamic Blowfish key
};
#endif /* LOGIN_INIT_H_ */

View File

@@ -0,0 +1,77 @@
#include "stdafx.h"
#include "L2Login_LoginFail.h"
/*
L2J:
protected void write()
{
writeC(0x01);
writeD(_reason.getCode());
}
REASON_SYSTEM_ERROR (0x01),
REASON_PASS_WRONG (0x02),
REASON_USER_OR_PASS_WRONG (0x03),
REASON_ACCESS_FAILED (0x04),
REASON_ACCOUNT_IN_USE (0x07),
REASON_SERVER_OVERLOADED (0x0f),
REASON_SERVER_MAINTENANCE (0x10),
REASON_TEMP_PASS_EXPIRED (0x11),
REASON_DUAL_BOX (0x23);
*/
L2Login_LoginFail::L2Login_LoginFail()
{
this->_initNull();
}
L2Login_LoginFail::L2Login_LoginFail( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
unsigned int L2Login_LoginFail::read_reason()
{
if( !this->canReadBytes(5) ) return 0;
this->readReset();
this->readUChar(); // pass packet type byte
return this->readUInt();
}
// converts login fail code to human-readable error string :)
// s must point to buffer at least 32 bytes long
void L2Login_LoginFail::getReasonStr( unsigned int code, char *s )
{
if( !s ) return;
strcpy( s, "REASON_UNKNOWN" );
switch( code )
{
case REASON_SYSTEM_ERROR : strcpy( s, "REASON_SYSTEM_ERROR" ); break;
case REASON_PASS_WRONG : strcpy( s, "REASON_PASS_WRONG" ); break;
case REASON_USER_OR_PASS_WRONG : strcpy( s, "REASON_USER_OR_PASS_WRONG" ); break;
case REASON_ACCESS_FAILED : strcpy( s, "REASON_ACCESS_FAILED" ); break;
case REASON_ACCOUNT_IN_USE : strcpy( s, "REASON_ACCOUNT_IN_USE" ); break;
case REASON_SERVER_OVERLOADED : strcpy( s, "REASON_SERVER_OVERLOADED" ); break;
case REASON_SERVER_MAINTENANCE : strcpy( s, "REASON_SERVER_MAINTENANCE" ); break;
case REASON_TEMP_PASS_EXPIRED : strcpy( s, "REASON_TEMP_PASS_EXPIRED" ); break;
case REASON_DUAL_BOX : strcpy( s, "REASON_DUAL_BOX" ); break;
}
}
bool L2Login_LoginFail::create( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x01 );
writeUChar( p_reasonCode & 0xFF );
return true;
}
bool L2Login_LoginFail::parse( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
if( !canReadBytes( 2 ) ) return false;
if( getPacketType() != 0x01 ) return false;
p_reasonCode = (unsigned int)readUChar();
return true;
}

View File

@@ -0,0 +1,33 @@
#ifndef L2LOGIN_LOGINFAIL_H_
#define L2LOGIN_LOGINFAIL_H_
#include "../L2LoginPacket.h"
class L2Login_LoginFail : public L2LoginPacket
{
public:
static const unsigned int REASON_SYSTEM_ERROR = 0x01;
static const unsigned int REASON_PASS_WRONG = 0x02;
static const unsigned int REASON_USER_OR_PASS_WRONG = 0x03;
static const unsigned int REASON_ACCESS_FAILED = 0x04;
static const unsigned int REASON_ACCOUNT_IN_USE = 0x07;
static const unsigned int REASON_SERVER_OVERLOADED = 0x0f;
static const unsigned int REASON_SERVER_MAINTENANCE = 0x10;
static const unsigned int REASON_TEMP_PASS_EXPIRED = 0x11;
static const unsigned int REASON_DUAL_BOX = 0x23;
public:
L2Login_LoginFail();
L2Login_LoginFail( const unsigned char *bytes, unsigned int length );
public:
unsigned int read_reason();
// converts login fail code to human-readable error string :)
// s must point to buffer at least 32 bytes long
static void getReasonStr( unsigned int code, char *s );
public:
bool create( L2_VERSION ver = L2_VERSION_T1 );
bool parse( L2_VERSION ver = L2_VERSION_T1 );
public:
unsigned int p_reasonCode;
};
#endif /*L2LOGIN_LOGINFAIL_H_*/

View File

@@ -0,0 +1,56 @@
#include "stdafx.h"
#include "L2Login_LoginOK.h"
L2Login_LoginOK::L2Login_LoginOK()
{
this->_initNull();
}
L2Login_LoginOK::L2Login_LoginOK( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
// read SessionKey #1 from packet
// sessionKey1 must point to 8-byte array
bool L2Login_LoginOK::read_sessionKey1( unsigned char *sessionKey1 )
{
if( !sessionKey1 ) return false;
// check packet size
if( this->real_size < 9 ) return false;
this->readReset();
this->readUChar(); // pass packet code byte
this->readBytes( sessionKey1, 8 ); // read 8 bytes of sessionKey1
return true;
}
bool L2Login_LoginOK::create( L2_VERSION ver /*= L2_VERSION_T23*/ )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x03 );
writeBytes( p_sessionKey1, 8 );
writeD( 0x00 );
writeD( 0x00 );
writeD( 0x000003ea ); // wtf?
writeD( 0x00 );
writeD( 0x00 );
writeD( 0x00 );
//writeB(new byte[16]); // 4 Ds
writeD( 0x00 );
writeD( 0x00 );
writeD( 0x00 );
writeD( 0x00 );
return true;
}
bool L2Login_LoginOK::parse( L2_VERSION ver /*= L2_VERSION_T23*/ )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x03 ) return false;
if( !canReadBytes( 8 ) ) return false; // we need at least 8 bytes of sessionKey1
readBytes( p_sessionKey1, 8 );
// ignore the rest
return true;
}

View File

@@ -0,0 +1,22 @@
#ifndef L2LOGIN_LOGINOK_H_
#define L2LOGIN_LOGINOK_H_
#include "../L2LoginPacket.h"
class L2Login_LoginOK : public L2LoginPacket
{
public:
L2Login_LoginOK();
L2Login_LoginOK( const unsigned char *bytes, unsigned int length );
public:
// read SessionKey #1 from packet
// SessionKey is 8-byte array
bool read_sessionKey1( unsigned char *sessionKey1 );
public:
bool create( L2_VERSION ver = L2_VERSION_T23 );
bool parse( L2_VERSION ver = L2_VERSION_T23 );
public:
unsigned char p_sessionKey1[8];
};
#endif /*L2LOGIN_LOGINOK_H_*/

View File

@@ -0,0 +1,64 @@
#include "stdafx.h"
#include "L2Login_PlayFail.h"
/*
writeC(0x06);
writeC(_reason.getCode());
*/
L2Login_PlayFail::L2Login_PlayFail()
{
this->_initNull();
}
L2Login_PlayFail::L2Login_PlayFail( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
unsigned char L2Login_PlayFail::read_reason()
{
if( this->canReadBytes(2) )
{
this->readReset();
this->readUChar();
return this->readUChar();
}
return 0;
}
// str must point to buffer at least 32 bytes long
bool L2Login_PlayFail::getReasonStr( unsigned char code, char *str )
{
if( !str ) return false;
strcpy( str, "REASON_UNKNOWN" );
switch( code )
{
case REASON_SYSTEM_ERROR: strcpy( str, "REASON_SYSTEM_ERROR" ); break;
case REASON_USER_OR_PASS_WRONG: strcpy( str, "REASON_USER_OR_PASS_WRONG" ); break;
case REASON3: strcpy( str, "REASON3" ); break;
case REASON_ACCESS_FAILED: strcpy( str, "REASON_ACCESS_FAILED" ); break;
case REASON_ACCOUNT_INFORMATION_INCORRECT: strcpy( str, "REASON_ACCOUNT_INFORMATION_INCORRECT" ); break;
case REASON_TOO_MANY_PLAYERS: strcpy( str, "REASON_TOO_MANY_PLAYERS" ); break;
}
return true;
}
bool L2Login_PlayFail::create( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
setPacketType( 0x06 );
writeUChar( p_reasonCode );
return true;
}
bool L2Login_PlayFail::parse( L2_VERSION ver /*= L2_VERSION_T1*/ )
{
UNREFERENCED_PARAMETER(ver);
if( getPacketType() != 0x06 ) return false;
if( !canReadBytes(1) ) return false;
p_reasonCode = readUChar();
return true;
}

Some files were not shown because too many files have changed in this diff Show More