Initial MSVC 2008 projects workspace
This commit is contained in:
30
l2detect/AboutDialog.cpp
Normal file
30
l2detect/AboutDialog.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "AboutDialog.h"
|
||||
|
||||
// EXTERNALS
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
|
||||
INT_PTR CALLBACK AboutDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: /*ConfigDlg_OnInitDialog( hDlg );*/ break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
case IDOK: EndDialog( hDlg, TRUE ); break;
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void AboutDialogStart( HWND hWndParent )
|
||||
{
|
||||
DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWndParent, AboutDialogProc, 0 );
|
||||
}
|
||||
6
l2detect/AboutDialog.h
Normal file
6
l2detect/AboutDialog.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_ABOUT_DLG
|
||||
#define H_ABOUT_DLG
|
||||
|
||||
void AboutDialogStart( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
434
l2detect/BinTree.cpp
Normal file
434
l2detect/BinTree.cpp
Normal file
@@ -0,0 +1,434 @@
|
||||
#include "stdafx.h"
|
||||
#include "BinTree.h"
|
||||
|
||||
BinTreeNode::BinTreeNode()
|
||||
{
|
||||
parent = left = right = NULL;
|
||||
key = 0;
|
||||
}
|
||||
|
||||
BinTreeNode::BinTreeNode( unsigned int keyInit )
|
||||
{
|
||||
parent = left = right = NULL;
|
||||
key = keyInit;
|
||||
//printf( "BinTreeNode() constructed with key %u\n", key );
|
||||
}
|
||||
|
||||
BinTreeNode::~BinTreeNode()
|
||||
{
|
||||
//printf( "~BinTreeNode: destoyed %u\n", key );
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
//=============================================================
|
||||
//=============================================================
|
||||
|
||||
BinTree::~BinTree()
|
||||
{
|
||||
deleteAll();
|
||||
}
|
||||
|
||||
void BinTree::deleteAll()
|
||||
{
|
||||
if( root )
|
||||
{
|
||||
del_recursive( root );
|
||||
delete root;
|
||||
root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BinTree::del_recursive( BinTreeNode *node )
|
||||
{
|
||||
if( !node ) return;
|
||||
if( node->left )
|
||||
{
|
||||
//printf( "cur %u; delete left\n", node->key );
|
||||
del_recursive( node->left );
|
||||
delete node->left;
|
||||
}
|
||||
if( node->right )
|
||||
{
|
||||
//printf( "cur %u; delete right\n", node->key );
|
||||
del_recursive( node->right );
|
||||
delete node->right;
|
||||
}
|
||||
/*node->left = NULL;
|
||||
node->right = NULL;
|
||||
node->key = 0;*/
|
||||
}
|
||||
|
||||
bool BinTree::addNode( BinTreeNode *node )
|
||||
{
|
||||
if( !node ) return false;
|
||||
if( !root )
|
||||
{
|
||||
root = node;
|
||||
root->parent = NULL;
|
||||
return true;
|
||||
}
|
||||
BinTreeNode *cur = root;
|
||||
//BinTreeNode *prev = root;
|
||||
while( 1 )
|
||||
{
|
||||
//prev = cur;
|
||||
if( node->key > cur->key )
|
||||
{
|
||||
if( cur->right == NULL )
|
||||
{
|
||||
//add to right
|
||||
node->parent = cur;
|
||||
cur->right = node;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = cur->right;
|
||||
}
|
||||
}
|
||||
else if( node->key < cur->key )
|
||||
{
|
||||
if( cur->left == NULL )
|
||||
{
|
||||
// add to left
|
||||
node->parent = cur;
|
||||
cur->left = node;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = cur->left;
|
||||
}
|
||||
}
|
||||
else if( node->key == cur->key )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// never executed!
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
bool BinTree::addNodeDebug( BinTreeNode *node, FILE *f )
|
||||
{
|
||||
if( !node )
|
||||
{
|
||||
fprintf( f, "BinTree::addNode(): node == NULL!\n" );
|
||||
return false;
|
||||
}
|
||||
if( !root )
|
||||
{
|
||||
root = node;
|
||||
root->parent = NULL;
|
||||
fprintf( f, "BinTree::addNodeDebug(): added node key %u to root\n", node->key );
|
||||
return true;
|
||||
}
|
||||
BinTreeNode *cur = root;
|
||||
//BinTreeNode *prev = root;
|
||||
while( 1 )
|
||||
{
|
||||
//prev = cur;
|
||||
if( node->key > cur->key )
|
||||
{
|
||||
if( cur->right == NULL )
|
||||
{
|
||||
//add to right
|
||||
node->parent = cur;
|
||||
cur->right = node;
|
||||
fprintf( f, "BinTree::addNodeDebug(): added node key %u to right of key %u\n",
|
||||
node->key, cur->key );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = cur->right;
|
||||
}
|
||||
}
|
||||
else if( node->key < cur->key )
|
||||
{
|
||||
if( cur->left == NULL )
|
||||
{
|
||||
// add to left
|
||||
node->parent = cur;
|
||||
cur->left = node;
|
||||
fprintf( f, "BinTree::addNodeDebug(): added node key %u to left of key %u\n",
|
||||
node->key, cur->key );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = cur->left;
|
||||
}
|
||||
}
|
||||
else if( node->key == cur->key )
|
||||
{
|
||||
fprintf( f, "BinTree::addNodeDebug(): key %u already exists\n", node->key );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
printf( "BinTree::addNode(): never executed!\n" );
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
BinTreeNode *BinTree::findNode( unsigned int key )
|
||||
{
|
||||
if( !root ) return NULL;
|
||||
BinTreeNode *cur = root;
|
||||
while( cur )
|
||||
{
|
||||
if( cur->key == key ) return cur;
|
||||
if( key > cur->key ) cur = cur->right;
|
||||
else if( key < cur->key ) cur = cur->left;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
bool BinTree::delNode( BinTreeNode *node )
|
||||
{
|
||||
if( !node ) return false;
|
||||
if( (node->left == NULL) && (node->right == NULL) )
|
||||
{
|
||||
if( node->parent )
|
||||
{
|
||||
if( node->parent->left == node ) node->parent->left = NULL;
|
||||
if( node->parent->right == node ) node->parent->right = NULL;
|
||||
}
|
||||
else root = NULL;
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( node->left && (node->right == NULL) )
|
||||
{
|
||||
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->left = node->left;
|
||||
}
|
||||
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->right = node->left;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->left->parent = node->parent;
|
||||
}
|
||||
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
root = node->left;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->left->parent = NULL;
|
||||
}
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( node->right && (node->left == NULL) )
|
||||
{
|
||||
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->left = node->right;
|
||||
}
|
||||
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->right = node->right;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->right->parent = node->parent;
|
||||
}
|
||||
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
root = node->right;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->right->parent = NULL;
|
||||
}
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( node->left && node->right )
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>...
|
||||
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
node->left->parent = node->parent;
|
||||
if( node->parent->left == node ) node->parent->left = node->left;
|
||||
if( node->parent->right == node ) node->parent->right = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
root = node->left;
|
||||
node->left->parent = NULL;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
addNode( node->right );
|
||||
delete node;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinTree::delNode( unsigned int key )
|
||||
{
|
||||
if( !root ) return false;
|
||||
BinTreeNode *node = findNode( key );
|
||||
if( node ) return delNode( node );
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
BinTreeNode *BinTree::findNodeDebug( unsigned int key, FILE *f )
|
||||
{
|
||||
if( !f ) return NULL;
|
||||
if( !root ) return NULL;
|
||||
fprintf( f, "BinTree::findNodeDebug( int key = %u )\n", key );
|
||||
BinTreeNode *cur = root;
|
||||
while( cur )
|
||||
{
|
||||
fprintf( f, "cur = 0x%p (key %u)\n", cur, cur->key );
|
||||
if( cur->key == key ) { fprintf( f, "found key %u\n", cur->key ); return cur; }
|
||||
if( key > cur->key ) { fprintf( f, "... > %u; right\n", cur->key ); cur = cur->right; continue; }
|
||||
if( key < cur->key ) { fprintf( f, "... < %u; left\n", cur->key ); cur = cur->left; continue; }
|
||||
}
|
||||
if( cur ) fprintf( f, "returning 0x%p key %u\n", cur, cur->key );
|
||||
else fprintf( f, "key %u not found\n", key );
|
||||
return cur;
|
||||
}
|
||||
|
||||
bool BinTree::delNodeDebug( unsigned int key, FILE *f )
|
||||
{
|
||||
if( !f || !root ) return false;
|
||||
BinTreeNode *del = findNodeDebug( key, f );
|
||||
if( del ) return delNodeDebug( del, f );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BinTree::delNodeDebug( BinTreeNode *node, FILE *f )
|
||||
{
|
||||
if( !node || !f ) return false;
|
||||
fprintf( f, "delNodeDebug: del node key %u, parent = 0x%p\n", node->key, node->parent );
|
||||
if( (node->left == NULL) && (node->right == NULL) )
|
||||
{
|
||||
fprintf( f, "case 0: no children\n" );
|
||||
if( node->parent )
|
||||
{
|
||||
if( node->parent->left == node ) node->parent->left = NULL;
|
||||
if( node->parent->right == node ) node->parent->right = NULL;
|
||||
}
|
||||
else root = NULL;
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( node->left && (node->right == NULL) )
|
||||
{
|
||||
fprintf( f, "case 1: left exists\n" );
|
||||
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->left = node->left;
|
||||
}
|
||||
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->right = node->left;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->left->parent = node->parent;
|
||||
}
|
||||
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
root = node->left;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->left->parent = NULL;
|
||||
}
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( node->right && (node->left == NULL) )
|
||||
{
|
||||
fprintf( f, "case 2: right exists\n" );
|
||||
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->left = node->right;
|
||||
}
|
||||
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
node->parent->right = node->right;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->right->parent = node->parent;
|
||||
}
|
||||
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
root = node->right;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
node->right->parent = NULL;
|
||||
}
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( node->left && node->right )
|
||||
{
|
||||
fprintf( f, "case 3: left and right exist\n" );
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>...
|
||||
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
node->left->parent = node->parent;
|
||||
if( node->parent->left == node ) node->parent->left = node->left;
|
||||
if( node->parent->right == node ) node->parent->right = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
root = node->left;
|
||||
node->left->parent = NULL;
|
||||
}
|
||||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
addNodeDebug( node->right, f );
|
||||
delete node;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void printTreeNode( FILE *f, int recur_count, BinTreeNode *node )
|
||||
{
|
||||
if( !node ) return;
|
||||
int i;
|
||||
//fprintf( f, "\n" );
|
||||
if( node->parent )
|
||||
{
|
||||
if( node->parent->left == node ) fprintf( f, "LEFT " );
|
||||
else if( node->parent->right == node ) fprintf( f, "RIGHT " );
|
||||
else fprintf( f, "Parent unknown??? " );
|
||||
}
|
||||
else fprintf( f, "ROOT " );
|
||||
for( i=0; i<recur_count; i++ ) fprintf( f, "." );
|
||||
fprintf( f, "%d (0x%p)\n", node->key, node );
|
||||
//fprintf( f, "\n" );
|
||||
if( node->left ) printTreeNode( f, recur_count+1, node->left );
|
||||
if( node->right ) printTreeNode( f, recur_count+1, node->right );
|
||||
}
|
||||
|
||||
void BinTree::printTree( FILE *f )
|
||||
{
|
||||
if( !f ) return;
|
||||
if( !root ) fprintf( f, "BinTree is empty!\n" );
|
||||
printTreeNode( f, 1, root );
|
||||
}
|
||||
|
||||
#endif
|
||||
47
l2detect/BinTree.h
Normal file
47
l2detect/BinTree.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef BINTREE_H_
|
||||
#define BINTREE_H_
|
||||
|
||||
class BinTreeNode
|
||||
{
|
||||
public:
|
||||
BinTreeNode();
|
||||
BinTreeNode( unsigned int keyInit );
|
||||
virtual ~BinTreeNode();
|
||||
public:
|
||||
BinTreeNode *parent;
|
||||
BinTreeNode *left;
|
||||
BinTreeNode *right;
|
||||
unsigned int key;
|
||||
};
|
||||
|
||||
class BinTree
|
||||
{
|
||||
public:
|
||||
BinTree() { root = NULL; }
|
||||
virtual ~BinTree();
|
||||
public:
|
||||
bool addNode( BinTreeNode *node );
|
||||
BinTreeNode *findNode( unsigned int key );
|
||||
bool delNode( BinTreeNode *node );
|
||||
bool delNode( unsigned int key );
|
||||
|
||||
void deleteAll();
|
||||
|
||||
BinTreeNode *getRoot() const { return this->root; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
public:
|
||||
bool addNodeDebug( BinTreeNode *node, FILE *f );
|
||||
BinTreeNode *findNodeDebug( unsigned int key, FILE *f );
|
||||
bool delNodeDebug( unsigned int key, FILE *f );
|
||||
bool delNodeDebug( BinTreeNode *node, FILE *f );
|
||||
void printTree( FILE *f );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void del_recursive( BinTreeNode *node );
|
||||
protected:
|
||||
BinTreeNode *root;
|
||||
};
|
||||
|
||||
#endif /* BINTREE_H_ */
|
||||
54
l2detect/BinTreeNode_Clan.cpp
Normal file
54
l2detect/BinTreeNode_Clan.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "stdafx.h"
|
||||
#include "BinTreeNode_Clan.h"
|
||||
|
||||
BinTreeNode_Clan::BinTreeNode_Clan(): BinTreeNode()
|
||||
{
|
||||
m_clanID = 0;
|
||||
m_clanName[0] = m_allyName[0] = 0;
|
||||
//
|
||||
//wcscpy( m_str_null, L"NULL" );
|
||||
}
|
||||
|
||||
BinTreeNode_Clan::BinTreeNode_Clan( unsigned int clanID,
|
||||
const wchar_t *clanName,
|
||||
const wchar_t *allyName ): BinTreeNode()
|
||||
{
|
||||
key = clanID;
|
||||
m_clanID = clanID;
|
||||
setClanName( clanName );
|
||||
setAllyName( allyName );
|
||||
//
|
||||
//wcscpy( m_str_null, L"NULL" );
|
||||
}
|
||||
|
||||
BinTreeNode_Clan::~BinTreeNode_Clan()
|
||||
{
|
||||
m_clanID = 0;
|
||||
m_clanName[0] = m_allyName[0] = 0;
|
||||
}
|
||||
|
||||
void BinTreeNode_Clan::setClanName( const wchar_t *clanName )
|
||||
{
|
||||
m_clanName[0] = 0;
|
||||
if( clanName ) wcsncpy( m_clanName, clanName, 127 );
|
||||
m_clanName[127] = 0;
|
||||
}
|
||||
|
||||
void BinTreeNode_Clan::setAllyName( const wchar_t *allyName )
|
||||
{
|
||||
m_allyName[0] = 0;
|
||||
if( allyName ) wcsncpy( m_allyName, allyName, 127 );
|
||||
m_allyName[127] = 0;
|
||||
}
|
||||
|
||||
const wchar_t *BinTreeNode_Clan::clanName() const
|
||||
{
|
||||
((class BinTreeNode_Clan *)this)->m_clanName[127] = 0; // for safe
|
||||
return m_clanName;
|
||||
}
|
||||
|
||||
const wchar_t *BinTreeNode_Clan::allyName() const
|
||||
{
|
||||
((class BinTreeNode_Clan *)this)->m_allyName[127] = 0; // for safe
|
||||
return m_allyName;
|
||||
}
|
||||
33
l2detect/BinTreeNode_Clan.h
Normal file
33
l2detect/BinTreeNode_Clan.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef BINTREENODE_CLAN_H_
|
||||
#define BINTREENODE_CLAN_H_
|
||||
#include "BinTree.h"
|
||||
|
||||
class BinTreeNode_Clan :public BinTreeNode
|
||||
{
|
||||
public:
|
||||
BinTreeNode_Clan();
|
||||
BinTreeNode_Clan( unsigned int clanID,
|
||||
const wchar_t *clanName,
|
||||
const wchar_t *allyName );
|
||||
virtual ~BinTreeNode_Clan();
|
||||
|
||||
public:
|
||||
void setClanID( unsigned int clanID ) { m_clanID = clanID; }
|
||||
void setClanName( const wchar_t *clanName );
|
||||
void setAllyName( const wchar_t *allyName );
|
||||
|
||||
public:
|
||||
unsigned int clanID() const { return m_clanID; }
|
||||
const wchar_t *clanName() const;
|
||||
const wchar_t *allyName() const;
|
||||
|
||||
protected:
|
||||
unsigned int m_clanID;
|
||||
wchar_t m_clanName[128];
|
||||
wchar_t m_allyName[128];
|
||||
|
||||
//protected:
|
||||
//wchar_t m_str_null[16];
|
||||
};
|
||||
|
||||
#endif /* BINTREENODE_CLAN_H_ */
|
||||
209
l2detect/CharArray.cpp
Normal file
209
l2detect/CharArray.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "CharArray.h"
|
||||
#include "WorldObjectTree.h"
|
||||
#include "RadarDllWnd.h" // to post updates
|
||||
|
||||
class L2Player *chars_array[CHARARRAY_MAX_CHARS];
|
||||
CRITICAL_SECTION charArray_cs;
|
||||
|
||||
//HWND charArray_updateHWND;
|
||||
//UINT charArray_updateMSG;
|
||||
UINT charArray_count;
|
||||
|
||||
void CharArray_Init()
|
||||
{
|
||||
charArray_count = 0;
|
||||
//charArray_updateHWND = NULL;
|
||||
//charArray_updateMSG = 0;
|
||||
InitializeCriticalSection( &charArray_cs );
|
||||
EnterCriticalSection( &charArray_cs );
|
||||
int i;
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
chars_array[i] = new L2Player();
|
||||
chars_array[i]->setUnused();
|
||||
}
|
||||
LeaveCriticalSection( &charArray_cs );
|
||||
}
|
||||
|
||||
void CharArray_Lock() { EnterCriticalSection( &charArray_cs ); }
|
||||
void CharArray_Unlock() { LeaveCriticalSection( &charArray_cs ); }
|
||||
|
||||
//void CharArray_SetUpdateCommand( HWND hWnd, UINT uMsg )
|
||||
//{
|
||||
// charArray_updateHWND = hWnd;
|
||||
// charArray_updateMSG = uMsg;
|
||||
//}
|
||||
//
|
||||
//void CharArray_PostUpdateMessage()
|
||||
//{
|
||||
// if( !charArray_updateHWND ) return;
|
||||
// if( charArray_updateMSG < WM_USER ) return;
|
||||
// PostMessage( charArray_updateHWND, charArray_updateMSG, 0, 0 );
|
||||
//}
|
||||
|
||||
void CharArray_Free()
|
||||
{
|
||||
int i;
|
||||
CharArray_Lock();
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
if( chars_array[i] ) delete chars_array[i];
|
||||
chars_array[i] = NULL;
|
||||
}
|
||||
CharArray_Unlock();
|
||||
charArray_count = 0;
|
||||
}
|
||||
|
||||
|
||||
void CharArray_AddCharInfo( L2Player *cha )
|
||||
{
|
||||
if( !cha ) return;
|
||||
//log_error( LOG_DEBUG, "CharList_Add: [%S] (oid %u) %s %s %s [%d,%d,%d -> %u]... ",
|
||||
// name, oid,
|
||||
// L2Data_getRace( race ), L2Data_getSex( sex ), L2Data_getClass( baseClass ),
|
||||
// x,y,z, heading );
|
||||
CharArray_Lock();
|
||||
|
||||
// first try to find existing char in world object tree
|
||||
int idx = -1;
|
||||
L2OBJECT_TYPE objType = L2OT_NONE;
|
||||
WorldObjectTree_GetInfoByObjectID( cha->objectID, &objType, &idx );
|
||||
if( (idx>=0) && (idx<CHARARRAY_MAX_CHARS) && (objType == L2OT_PC) )
|
||||
{
|
||||
// update info on existing
|
||||
if( !chars_array[idx] )
|
||||
{
|
||||
CharArray_Unlock();
|
||||
return;
|
||||
}
|
||||
memcpy( chars_array[idx], cha, sizeof(class L2Player) );
|
||||
//log_error( LOG_USERAI, "Char: Updated idx [%d] [%S]\n", idx, cha->name() );
|
||||
// update in radar window
|
||||
RadarWnd_UpdChar( cha->objectID );
|
||||
}
|
||||
else // add new
|
||||
{
|
||||
idx = CharArray_FindFreeIndex();
|
||||
if( idx >= 0 )
|
||||
{
|
||||
//chars_array[idx]->setFromOther( cha );
|
||||
memcpy( chars_array[idx], cha, sizeof(class L2Player) );
|
||||
charArray_count++;
|
||||
// add char to world object tree
|
||||
WorldObjectTree_AddObject( cha->objectID, L2OT_PC, idx );
|
||||
//log_error( LOG_USERAI, "Char: added new [%S] to idx[%d]\n", cha->name(), idx );
|
||||
// add to radar window
|
||||
RadarWnd_AddChar( cha->objectID );
|
||||
}
|
||||
else log_error( LOG_ERROR, "Error adding character [%S] to chars array! idx = %d\n", cha->getName(), idx );
|
||||
}
|
||||
CharArray_Unlock();
|
||||
}
|
||||
|
||||
void CharArray_DeleteCharByObjectID( unsigned int objectID )
|
||||
{
|
||||
CharArray_Lock();
|
||||
BOOL bDelOK = 0;
|
||||
int idx = CharArray_FindCharByObjectID( objectID );
|
||||
if( (idx>=0) && (idx<CHARARRAY_MAX_CHARS) )
|
||||
{
|
||||
chars_array[idx]->setUnused();
|
||||
bDelOK = TRUE;
|
||||
charArray_count--;
|
||||
}
|
||||
CharArray_Unlock();
|
||||
if( bDelOK ) //CharArray_PostUpdateMessage();
|
||||
RadarWnd_DelChar( objectID );
|
||||
}
|
||||
|
||||
void CharArray_DeleteCharByIdx( int idx )
|
||||
{
|
||||
BOOL bDelOK = FALSE;
|
||||
CharArray_Lock();
|
||||
if( (idx>=0) && (idx<CHARARRAY_MAX_CHARS) )
|
||||
{
|
||||
if( chars_array[idx] )
|
||||
{
|
||||
unsigned int objectID = chars_array[idx]->objectID;
|
||||
//log_error( LOG_USERAI, "Char: Deleted [%S] from [%d]\n", chars_array[idx]->name(), idx );
|
||||
chars_array[idx]->setUnused();
|
||||
bDelOK = TRUE;
|
||||
charArray_count--;
|
||||
// delete from WorldObjectTree
|
||||
WorldObjectTree_DelObject( objectID );
|
||||
RadarWnd_DelChar( objectID );
|
||||
}
|
||||
}
|
||||
CharArray_Unlock();
|
||||
//if( bDelOK ) CharArray_PostUpdateMessage();
|
||||
}
|
||||
|
||||
void CharArray_DeleteAll()
|
||||
{
|
||||
CharArray_Lock();
|
||||
int i;
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
if( chars_array[i] ) chars_array[i]->setUnused();
|
||||
}
|
||||
charArray_count = 0;
|
||||
CharArray_Unlock();
|
||||
}
|
||||
|
||||
/*void CharList_Display( FILE *f )
|
||||
{
|
||||
if( !f || !bt_chars ) return;
|
||||
CharList_Lock();
|
||||
fprintf( f, "===== Chars list =====\n" );
|
||||
BinTreeNode *root = bt_chars->getRoot();
|
||||
if( !root ) fprintf( f, "Chars list empty!\n" );
|
||||
else CharList_displayNode( f, root );
|
||||
fprintf( f, "======================\n" );
|
||||
//bt_chars->printTree( f );
|
||||
CharList_Unlock();
|
||||
}*/
|
||||
|
||||
unsigned int CharArray_GetCount() { return charArray_count; }
|
||||
|
||||
int CharArray_FindCharByObjectID( unsigned int objectID )
|
||||
{
|
||||
int ret = -1;
|
||||
int i;
|
||||
CharArray_Lock();
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
if( chars_array[i] == NULL ) continue;
|
||||
if( chars_array[i]->objectID == objectID )
|
||||
{
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CharArray_Unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CharArray_FindFreeIndex()
|
||||
{
|
||||
int i;
|
||||
CharArray_Lock();
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
if( chars_array[i] == NULL )
|
||||
{
|
||||
chars_array[i] = new L2Player(); // allocate new
|
||||
chars_array[i]->setUnused(); // and set as unused
|
||||
CharArray_Unlock();
|
||||
return i;
|
||||
}
|
||||
if( chars_array[i]->isUnused() )
|
||||
{
|
||||
CharArray_Unlock(); // just return index...
|
||||
return i;
|
||||
}
|
||||
}
|
||||
CharArray_Unlock();
|
||||
return -1;
|
||||
}
|
||||
26
l2detect/CharArray.h
Normal file
26
l2detect/CharArray.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CHARLIST_H_
|
||||
#define CHARLIST_H_
|
||||
|
||||
#define CHARARRAY_MAX_CHARS 1024
|
||||
|
||||
extern class L2Player *chars_array[CHARARRAY_MAX_CHARS];
|
||||
|
||||
void CharArray_Init();
|
||||
void CharArray_Free();
|
||||
|
||||
void CharArray_Lock();
|
||||
void CharArray_Unlock();
|
||||
|
||||
void CharArray_AddCharInfo( L2Player *cha );
|
||||
void CharArray_DeleteCharByObjectID( unsigned int objectID );
|
||||
void CharArray_DeleteCharByIdx( int idx );
|
||||
void CharArray_DeleteAll();
|
||||
|
||||
int CharArray_FindCharByObjectID( unsigned int objectID );
|
||||
int CharArray_FindFreeIndex();
|
||||
|
||||
//void CharArray_Display( FILE *f );
|
||||
//void CharArray_SetUpdateCommand( HWND hWnd, UINT uMsg );
|
||||
unsigned int CharArray_GetCount();
|
||||
|
||||
#endif /* CHARLIST_H_ */
|
||||
227
l2detect/ClanList.cpp
Normal file
227
l2detect/ClanList.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "ClanList.h"
|
||||
#include "BinTreeNode_Clan.h"
|
||||
|
||||
BinTree *bt_clans = NULL;
|
||||
HWND clanList_updateHWND;
|
||||
UINT clanList_updateMSG;
|
||||
CRITICAL_SECTION clanList_cs;
|
||||
UINT clanList_count;
|
||||
|
||||
void ClanList_Init()
|
||||
{
|
||||
clanList_count = 0;
|
||||
clanList_updateHWND = NULL;
|
||||
clanList_updateMSG = 0;
|
||||
InitializeCriticalSection( &clanList_cs );
|
||||
EnterCriticalSection( &clanList_cs );
|
||||
if( bt_clans == NULL )
|
||||
{
|
||||
log_error( LOG_DEBUG, "ClanList_Init(): create bintree\n" );
|
||||
bt_clans = new BinTree();
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_DEBUG, "ClanList_Init(): clear bintree\n" );
|
||||
bt_clans->deleteAll();
|
||||
}
|
||||
LeaveCriticalSection( &clanList_cs );
|
||||
}
|
||||
|
||||
void ClanList_Lock() { EnterCriticalSection( &clanList_cs ); }
|
||||
void ClanList_Unlock() { LeaveCriticalSection( &clanList_cs ); }
|
||||
|
||||
void ClanList_SetUpdateCommand( HWND hWnd, UINT uMsg )
|
||||
{
|
||||
clanList_updateHWND = hWnd;
|
||||
clanList_updateMSG = uMsg;
|
||||
}
|
||||
|
||||
void ClanList_SendUpdate()
|
||||
{
|
||||
if( !clanList_updateHWND ) return;
|
||||
if( clanList_updateMSG < WM_USER ) return;
|
||||
PostMessage( clanList_updateHWND, clanList_updateMSG, 0, 0 );
|
||||
}
|
||||
|
||||
void ClanList_Free()
|
||||
{
|
||||
if( !bt_clans ) log_error( LOG_DEBUG, "ClanList_Free() - already NULL\n" );
|
||||
else
|
||||
{
|
||||
ClanList_Lock();
|
||||
delete bt_clans;
|
||||
bt_clans = NULL;
|
||||
ClanList_Unlock();
|
||||
ClanList_SendUpdate();
|
||||
log_error( LOG_DEBUG, "ClanList_Free() - freed\n" );
|
||||
}
|
||||
clanList_count = 0;
|
||||
}
|
||||
|
||||
void ClanList_Add( unsigned int clanID, const wchar_t *clanName, const wchar_t *allyName )
|
||||
{
|
||||
if( !clanName || !allyName ) return;
|
||||
log_error( LOG_DEBUG, "ClanList_Add: [%S] (id %u) [%S]... ", clanName, clanID, allyName );
|
||||
|
||||
ClanList_Lock();
|
||||
if( !bt_clans )
|
||||
{
|
||||
log_error( LOG_DEBUG, " (BinTree created)... \n" );
|
||||
bt_clans = new BinTree();
|
||||
}
|
||||
BinTreeNode_Clan *node = new BinTreeNode_Clan( clanID, clanName, allyName );
|
||||
|
||||
// first try to find existing char
|
||||
BinTreeNode *existing = bt_clans->findNode( clanID );
|
||||
if( existing )
|
||||
{
|
||||
// update info on existing
|
||||
BinTreeNode_Clan *cl = (BinTreeNode_Clan *)existing;
|
||||
cl->setClanName( clanName );
|
||||
cl->setAllyName( allyName );
|
||||
cl->setClanID( clanID );
|
||||
//printf( "Updated info for [%S]\n", clanName );
|
||||
}
|
||||
else // add new
|
||||
{
|
||||
//if( bt_clans->addNodeDebug( node, stdout ) ) log_error_np( LOG_DEBUG, "OK\n" );
|
||||
if( bt_clans->addNode( node ) )
|
||||
{
|
||||
clanList_count++;
|
||||
log_error_np( LOG_DEBUG, "OK\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error_np( LOG_DEBUG, "FAILED\n" );
|
||||
log_error( LOG_ERROR, "Error adding clan [%S] to clan list!\n", clanName );
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
ClanList_Unlock();
|
||||
ClanList_SendUpdate();
|
||||
}
|
||||
|
||||
void ClanList_Delete( unsigned int clanID )
|
||||
{
|
||||
if( !bt_clans ) return;
|
||||
log_error( LOG_DEBUG, "ClanList_Delete( %u )... ", clanID );
|
||||
//if( bt_clans->delNodeDebug( oid, stdout ) ) log_error_np( LOG_DEBUG, "OK\n" );
|
||||
ClanList_Lock();
|
||||
if( bt_clans->delNode( clanID ) )
|
||||
{
|
||||
clanList_count--;
|
||||
log_error_np( LOG_DEBUG, "OK\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error_np( LOG_DEBUG, "FAILED\n" );
|
||||
//log_error( LOG_ERROR, "Error deleting object %u from chars list!\n", oid );
|
||||
}
|
||||
ClanList_Unlock();
|
||||
ClanList_SendUpdate();
|
||||
}
|
||||
|
||||
void ClanList_DeleteAll()
|
||||
{
|
||||
if( !bt_clans ) return;
|
||||
ClanList_Lock();
|
||||
bt_clans->deleteAll();
|
||||
clanList_count = 0;
|
||||
ClanList_Unlock();
|
||||
ClanList_SendUpdate();
|
||||
}
|
||||
|
||||
void ClanList_displayNode( FILE *f, BinTreeNode *node )
|
||||
{
|
||||
if( !f || !node ) return;
|
||||
BinTreeNode_Clan *btn = (BinTreeNode_Clan *)node;
|
||||
fprintf( f, " %S Ally %S [%u]\n", btn->clanName(), btn->allyName(), btn->clanID() );
|
||||
if( node->left ) ClanList_displayNode( f, node->left );
|
||||
if( node->right ) ClanList_displayNode( f, node->right );
|
||||
}
|
||||
|
||||
void ClanList_Display( FILE *f )
|
||||
{
|
||||
if( !f || !bt_clans ) return;
|
||||
ClanList_Lock();
|
||||
fprintf( f, "===== Clans list =====\n" );
|
||||
BinTreeNode *root = bt_clans->getRoot();
|
||||
if( !root ) fprintf( f, "Clans list empty!\n" );
|
||||
else ClanList_displayNode( f, root );
|
||||
fprintf( f, "======================\n" );
|
||||
//bt_clans->printTree( f );
|
||||
ClanList_Unlock();
|
||||
}
|
||||
|
||||
unsigned int ClanList_GetCount() { return clanList_count; }
|
||||
|
||||
void ClanList_GetClansArray_ProcessNode( BinTreeNode_Clan **clans_array, int *pi, BinTreeNode *cur )
|
||||
{
|
||||
if( !cur || !clans_array || !pi ) return;
|
||||
BinTreeNode_Clan *cl = (BinTreeNode_Clan *)cur;
|
||||
clans_array[(*pi)] = new BinTreeNode_Clan( (*cl) );
|
||||
clans_array[(*pi)]->left = clans_array[(*pi)]->right = NULL;
|
||||
(*pi) = (*pi) + 1;
|
||||
if( cur->left ) ClanList_GetClansArray_ProcessNode( clans_array, pi, cur->left );
|
||||
if( cur->right ) ClanList_GetClansArray_ProcessNode( clans_array, pi, cur->right );
|
||||
}
|
||||
|
||||
void *ClanList_GetClansArray()
|
||||
{
|
||||
if( !bt_clans ) return NULL;
|
||||
if( clanList_count <= 0 )
|
||||
{
|
||||
clanList_count = 0;
|
||||
return NULL;
|
||||
}
|
||||
BinTreeNode_Clan **clans_array = (BinTreeNode_Clan **)malloc( (sizeof(void *) * clanList_count ) );
|
||||
if( !clans_array ) return NULL;
|
||||
|
||||
int i;
|
||||
for( i=0; i<(int)clanList_count; i++ ) clans_array[i] = NULL;
|
||||
BinTreeNode *cur;
|
||||
|
||||
ClanList_Lock();
|
||||
|
||||
cur = bt_clans->getRoot();
|
||||
if( !cur )
|
||||
{
|
||||
ClanList_Unlock();
|
||||
free( clans_array );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
ClanList_GetClansArray_ProcessNode( clans_array, &i, cur );
|
||||
|
||||
ClanList_Unlock();
|
||||
|
||||
return clans_array;
|
||||
}
|
||||
|
||||
void ClanList_FreeClansArray( void *p )
|
||||
{
|
||||
if( !p ) return;
|
||||
free( p );
|
||||
}
|
||||
|
||||
void ClanList_GetClanNameByID( unsigned int clanID, TCHAR *out )
|
||||
{
|
||||
if( !out || !bt_clans ) return;
|
||||
out[0] = 0;
|
||||
ClanList_Lock();
|
||||
BinTreeNode_Clan *cl = (BinTreeNode_Clan *)bt_clans->findNode( clanID );
|
||||
if( !cl )
|
||||
{
|
||||
ClanList_Unlock();
|
||||
return;
|
||||
}
|
||||
#if defined(UNICODE) || defined(_UNICODE)
|
||||
_tcscpy( out, cl->clanName() );
|
||||
#else
|
||||
WideCharToMultiByte( CP_ACP, 0, cl->clanName(), -1, out, 127, NULL, NULL );
|
||||
#endif
|
||||
ClanList_Unlock();
|
||||
}
|
||||
22
l2detect/ClanList.h
Normal file
22
l2detect/ClanList.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef CLANLIST_H_
|
||||
#define CLANLIST_H_
|
||||
|
||||
void ClanList_Init();
|
||||
void ClanList_Free();
|
||||
|
||||
void ClanList_Add( unsigned int clanID, const wchar_t *clanName, const wchar_t *allyName );
|
||||
void ClanList_Delete( unsigned int clanID );
|
||||
void ClanList_DeleteAll();
|
||||
|
||||
void ClanList_Display( FILE *f );
|
||||
|
||||
void ClanList_SetUpdateCommand( HWND hWnd, UINT uMsg );
|
||||
|
||||
unsigned int ClanList_GetCount();
|
||||
|
||||
void *ClanList_GetClansArray();
|
||||
void ClanList_FreeClansArray( void *p );
|
||||
|
||||
void ClanList_GetClanNameByID( unsigned int clanID, TCHAR *out );
|
||||
|
||||
#endif /* CLANLIST_H_ */
|
||||
163
l2detect/ClanWarList.cpp
Normal file
163
l2detect/ClanWarList.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "stdafx.h"
|
||||
#include "ClanWarList.h"
|
||||
#include "Logger.h"
|
||||
|
||||
ClanWarList::ClanWarList()
|
||||
{
|
||||
int i;
|
||||
numDeclared = numUnderAttack = 0;
|
||||
for( i=0; i<MAX_CLANWARS; i++ )
|
||||
{
|
||||
cnDeclared[i] = NULL;
|
||||
cnUnderAttack[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ClanWarList::~ClanWarList()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void ClanWarList::clear()
|
||||
{
|
||||
int i;
|
||||
numDeclared = numUnderAttack = 0;
|
||||
for( i=0; i<MAX_CLANWARS; i++ )
|
||||
{
|
||||
if( cnDeclared[i] ) free( cnDeclared[i] );
|
||||
if( cnUnderAttack[i] ) free( cnUnderAttack[i] );
|
||||
cnDeclared[i] = NULL;
|
||||
cnUnderAttack[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ClanWarList::clearDeclared()
|
||||
{
|
||||
int i;
|
||||
numDeclared = 0;
|
||||
for( i=0; i<MAX_CLANWARS; i++ )
|
||||
{
|
||||
if( cnDeclared[i] ) free( cnDeclared[i] );
|
||||
cnDeclared[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ClanWarList::clearUnderAttack()
|
||||
{
|
||||
int i;
|
||||
numUnderAttack = 0;
|
||||
for( i=0; i<MAX_CLANWARS; i++ )
|
||||
{
|
||||
if( cnUnderAttack[i] ) free( cnUnderAttack[i] );
|
||||
cnUnderAttack[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*void ClanWarList::parse_PledgeReceiveWarList( const unsigned char *bytes, unsigned int length )
|
||||
{
|
||||
if( !bytes || (length<1) ) return;
|
||||
L2GamePacket *p = new L2GamePacket( bytes, length );*/
|
||||
void ClanWarList::parse_PledgeReceiveWarList( void *l2_game_packet )
|
||||
{
|
||||
if( !l2_game_packet ) return;
|
||||
L2GamePacket *p = (L2GamePacket *)l2_game_packet;
|
||||
//
|
||||
p->getPacketType(); // 0xFE
|
||||
p->readUShort(); // 0x003F
|
||||
//
|
||||
int i;
|
||||
wchar_t *strTemp;
|
||||
int tab = p->readInt();
|
||||
// clear data
|
||||
switch( tab )
|
||||
{
|
||||
case 0: clearDeclared(); break;
|
||||
case 1: clearUnderAttack(); break;
|
||||
}
|
||||
//
|
||||
p->readInt(); // page, always 0x00.. on L2J
|
||||
int warsCount = p->readInt();
|
||||
for( i=0; i<warsCount; i++ )
|
||||
{
|
||||
strTemp = p->readUnicodeString(); // clan name
|
||||
p->readInt(); // ??
|
||||
p->readInt(); // ??
|
||||
// add
|
||||
switch( tab )
|
||||
{
|
||||
case 0: { cnDeclared[i] = strTemp; numDeclared++; } break;
|
||||
case 1: { cnUnderAttack[i] = strTemp; numUnderAttack++; } break;
|
||||
}
|
||||
}
|
||||
//delete p; // packet deleted by calling function
|
||||
#ifdef _DEBUG
|
||||
log_error( LOG_USERAI, "PledgeReceiveWarList results: %d declared, %d under attack\n", numDeclared, numUnderAttack );
|
||||
//log_error( LOG_USERAI, "Declared: " );
|
||||
//for( i=0; i<numDeclared; i++ ) log_error_np( LOG_OK, "[%S] ", cnDeclared[i] );
|
||||
//log_error_np( LOG_USERAI, "\n" );
|
||||
//log_error( LOG_USERAI, "Under attack: " );
|
||||
//for( i=0; i<numUnderAttack; i++ ) log_error_np( LOG_OK, "[%S] ", cnUnderAttack[i] );
|
||||
//log_error_np( LOG_USERAI, "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
protected void writeImpl()
|
||||
{
|
||||
writeC(0xfe); // FE:3F PledgeReceiveWarList
|
||||
writeH(0x3f);
|
||||
|
||||
writeD(_tab); // type : 0 = Declared, 1 = Under Attack
|
||||
writeD(0x00); // page
|
||||
writeD(_tab == 0 ? _clan.getWarList().size() : _clan.getAttackerList().size()); // warsCount
|
||||
for(Integer i : _tab == 0 ? _clan.getWarList() : _clan.getAttackerList())
|
||||
{
|
||||
L2Clan clan = ClanTable.getInstance().getClan(i);
|
||||
if (clan == null) continue;
|
||||
|
||||
writeS(clan.getName());
|
||||
writeD(_tab); //??
|
||||
writeD(_tab); //??
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
CLANWARSTATE ClanWarList::getWarForClan( const wchar_t *wszClanName )
|
||||
{
|
||||
if( !wszClanName ) return CLANWAR_NOWAR;
|
||||
if( (numDeclared == 0) && (numUnderAttack == 0) ) return CLANWAR_NOWAR;
|
||||
CLANWARSTATE ret;;
|
||||
int declared, underattack;
|
||||
int i;
|
||||
// declared?
|
||||
declared = 0;
|
||||
if( numDeclared > 0 )
|
||||
{
|
||||
for( i=0; i<numDeclared; i++ )
|
||||
{
|
||||
if( wcscmp( wszClanName, cnDeclared[i] ) == 0 )
|
||||
{
|
||||
declared = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// underattack?
|
||||
underattack = 0;
|
||||
if( numUnderAttack > 0 )
|
||||
{
|
||||
for( i=0; i<numUnderAttack; i++ )
|
||||
{
|
||||
if( wcscmp( wszClanName, cnUnderAttack[i] ) == 0 )
|
||||
{
|
||||
underattack = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = CLANWAR_NOWAR;
|
||||
if( declared && !underattack ) ret = CLANWAR_DECLARED;
|
||||
if( !declared && underattack ) ret = CLANWAR_UNDERATTACK;
|
||||
if( declared && underattack ) ret = CLANWAR_BOTH;
|
||||
return ret;
|
||||
}
|
||||
34
l2detect/ClanWarList.h
Normal file
34
l2detect/ClanWarList.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef H_CLAN_WAR_LIST
|
||||
#define H_CLAN_WAR_LIST
|
||||
|
||||
#define MAX_CLANWARS 32
|
||||
|
||||
typedef enum eCLANWARSTATE
|
||||
{
|
||||
CLANWAR_NOWAR = 0,
|
||||
CLANWAR_DECLARED,
|
||||
CLANWAR_UNDERATTACK,
|
||||
CLANWAR_BOTH
|
||||
} CLANWARSTATE, *LPCLANWARSTATE;
|
||||
|
||||
class ClanWarList
|
||||
{
|
||||
public:
|
||||
ClanWarList();
|
||||
~ClanWarList();
|
||||
void clear();
|
||||
void clearDeclared();
|
||||
void clearUnderAttack();
|
||||
//void parse_PledgeReceiveWarList( const unsigned char *bytes, unsigned int length );
|
||||
void parse_PledgeReceiveWarList( void *l2_game_packet );
|
||||
public:
|
||||
CLANWARSTATE getWarForClan( const wchar_t *wszClanName );
|
||||
public:
|
||||
int numDeclared;
|
||||
int numUnderAttack;
|
||||
wchar_t *cnDeclared[MAX_CLANWARS];
|
||||
wchar_t *cnUnderAttack[MAX_CLANWARS];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
39
l2detect/ClassPri.cpp
Normal file
39
l2detect/ClassPri.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "stdafx.h"
|
||||
#include "ClassPri.h"
|
||||
|
||||
ClassPriorities::ClassPriorities()
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<L2MaxClasses; i++ )
|
||||
m_pri[i] = 0;
|
||||
}
|
||||
|
||||
ClassPriorities::~ClassPriorities()
|
||||
{
|
||||
}
|
||||
|
||||
void ClassPriorities::initDefaultPriorityList()
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<L2MaxClasses; i++ ) setPriForClass( i, 10 );
|
||||
setPriForClass( 97, 500 );
|
||||
setPriForClass( 105, 400 );
|
||||
setPriForClass( 16, 200 );
|
||||
setPriForClass( 30, 100 );
|
||||
}
|
||||
|
||||
void ClassPriorities::setPriForClass( int classId, int pri )
|
||||
{
|
||||
if( classId<0 || (classId>=L2MaxClasses) || (pri<0) ) return;
|
||||
if( classId>=58 && classId<=87 ) return; // unused intreval 1
|
||||
if( classId>=119 && classId<=122 ) return; // unused intreval 1
|
||||
m_pri[classId] = pri;
|
||||
}
|
||||
|
||||
int ClassPriorities::getPriForClass( int classId ) const
|
||||
{
|
||||
if( classId<0 || (classId>=L2MaxClasses) ) return -1;
|
||||
if( classId>=58 && classId<=87 ) return -1; // unused intreval 1
|
||||
if( classId>=119 && classId<=122 ) return -1; // unused intreval 1
|
||||
return m_pri[classId];
|
||||
}
|
||||
20
l2detect/ClassPri.h
Normal file
20
l2detect/ClassPri.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef L2MaxClasses // if L2Data.h from L2Packets.h is not included...
|
||||
#define L2MaxClasses 137 // >= Kamael
|
||||
#endif
|
||||
|
||||
class ClassPriorities
|
||||
{
|
||||
public:
|
||||
ClassPriorities();
|
||||
~ClassPriorities();
|
||||
|
||||
public:
|
||||
void initDefaultPriorityList();
|
||||
void setPriForClass( int classId, int pri );
|
||||
int getPriForClass( int classId ) const;
|
||||
|
||||
protected:
|
||||
int m_pri[L2MaxClasses];
|
||||
};
|
||||
274
l2detect/ConfigDlg.cpp
Normal file
274
l2detect/ConfigDlg.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "ConfigDlg.h"
|
||||
#include "Logger.h"
|
||||
// listeners
|
||||
#include "LoginListener.h"
|
||||
#include "GameListener.h"
|
||||
|
||||
// EXTERNALS
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
// global app configuration
|
||||
extern CConfig g_cfg;
|
||||
extern LoginListener *g_plogin;
|
||||
extern GameListener *g_pgame;
|
||||
extern char g_error_logger_strtype[LOG_LEVELS][16]; // Warning!!! HACK!!!
|
||||
|
||||
void ConfigDlg_OnInitDialog( HWND hDlg );
|
||||
void ConfigDlg_OnOK( HWND hDlg, BOOL bEndDialog );
|
||||
void ConfigDlg_OnApply( HWND hDlg );
|
||||
void ConfigDlg_UpateEnabledControls( HWND hDlg );
|
||||
|
||||
INT_PTR CALLBACK ConfigDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: ConfigDlg_OnInitDialog( hDlg ); break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
case IDOK: ConfigDlg_OnOK( hDlg, TRUE ); break;
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
case IDC_APPLY: ConfigDlg_OnApply( hDlg ); break;
|
||||
}
|
||||
ConfigDlg_UpateEnabledControls( hDlg );
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ConfigDialogStart( HWND hWndParent )
|
||||
{
|
||||
DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_CONFIG), hWndParent, ConfigDlgProc, 0 );
|
||||
}
|
||||
|
||||
void ConfigDlg_OnInitDialog( HWND hDlg )
|
||||
{
|
||||
HWND h;
|
||||
int i;
|
||||
|
||||
// L2 Version
|
||||
h = GetDlgItem( hDlg, IDC_CB_L2VER );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 1 - The Kamael") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 1.5 - Hellbound") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2 - Gracia Part 1") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2.2 - Gracia Part 2") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2.3 - Gracia Final") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2.4 - Gracia Epilogue") );
|
||||
SendMessage( h, CB_SETCURSEL, (WPARAM)g_cfg.L2_version, 0 );
|
||||
// L2 Client Version
|
||||
h = GetDlgItem( hDlg, IDC_CB_L2CVER );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 1 - The Kamael") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 1.5 - Hellbound") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2 - Gracia Part 1") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2.2 - Gracia Part 2") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2.3 - Gracia Final") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("Chaotic Throne 2.4 - Gracia Epilogue") );
|
||||
SendMessage( h, CB_SETCURSEL, (WPARAM)g_cfg.L2_client_version, 0 );
|
||||
|
||||
// full mode enable
|
||||
CheckDlgButton( hDlg, IDC_C_ENABLE_MODGT, g_cfg.EnableModifyGameTraffic );
|
||||
// override game protocolversion
|
||||
SetDlgItemInt( hDlg, IDC_E_OVERRIDE_GPV, g_cfg.OverrideGameProtocolVersion, FALSE );
|
||||
// thread priority raise enable
|
||||
CheckDlgButton( hDlg, IDC_C_ENABLE_THREADPRI, g_cfg.ThreadProirityRaiseEnable );
|
||||
// reply L2J GameGuardQuery
|
||||
CheckDlgButton( hDlg, IDC_C_GAMEGUARDREPLY, g_cfg.ReplyL2JGameGuardQuery );
|
||||
// Gracia Epilogue protocol 148 hacks
|
||||
CheckDlgButton( hDlg, IDC_C_EPILOGUE_148_146, g_cfg.GraciaEpilogueProtocol_148_hacks );
|
||||
|
||||
// L2Walker_DropRequestGMList
|
||||
CheckDlgButton( hDlg, IDC_C_L2WDROPGMLIST, g_cfg.L2Walker_DropRequestGMList );
|
||||
// L2Walker_FixMoveBackwardToLocation
|
||||
CheckDlgButton( hDlg, IDC_C_L2WMOVEFIX, g_cfg.L2Walker_FixMoveBackwardToLocation );
|
||||
// L2Walker_FixChangeWaitType2
|
||||
CheckDlgButton( hDlg, IDC_C_L2WSITFIX, g_cfg.L2Walker_FixChangeWaitType2 );
|
||||
// L2Walker_InjectStatusUpdate
|
||||
CheckDlgButton( hDlg, IDC_C_L2WALKER_INJECTSTATUSUPDATE, g_cfg.L2Walker_InjectStatusUpdate );
|
||||
|
||||
// log level
|
||||
h = GetDlgItem( hDlg, IDC_CB_LOGLEVEL );
|
||||
for( i=LOG_OK; i<=LOGLEVEL_LAST; i++ )
|
||||
{
|
||||
char *pstr = g_error_logger_strtype[i];
|
||||
SendMessageA( h, CB_ADDSTRING, 0, (LPARAM)pstr );
|
||||
}
|
||||
SendMessage( h, CB_SETCURSEL, (WPARAM)(int)g_cfg.WarnMessageLevel, 0 );
|
||||
|
||||
// Log Game Packets
|
||||
CheckDlgButton( hDlg, IDC_C_LOGGAMEP, g_cfg.LogGamePackets );
|
||||
// Log packets FileName Prefix
|
||||
SetDlgItemTextA( hDlg, IDC_E_LOGFNPREFIX, g_cfg.LogGameFileNamePrefix );
|
||||
// warn unknown packets
|
||||
CheckDlgButton( hDlg, IDC_C_WARNUNKP, g_cfg.WarnUnknownPacketsToStdout );
|
||||
|
||||
// FakeListenLoginPort
|
||||
SetDlgItemInt( hDlg, IDC_E_FLPORT, g_cfg.FakeListenLoginPort, TRUE );
|
||||
// FakeListenGamePort
|
||||
SetDlgItemInt( hDlg, IDC_E_FGPORT, g_cfg.FakeListenGamePort, TRUE );
|
||||
// RealLoginServerIP
|
||||
SetDlgItemTextA( hDlg, IDC_E_REALIP, g_cfg.RealLoginServerIP );
|
||||
// RealLoginServerPort
|
||||
SetDlgItemInt( hDlg, IDC_E_REALPORT, g_cfg.RealLoginServerPort, TRUE );
|
||||
// PlayGameServerNo
|
||||
//SetDlgItemInt( hDlg, IDC_E_PLAYGSNO, g_cfg.PlayGameServerNo, TRUE );
|
||||
|
||||
// forced game server select setting
|
||||
SetDlgItemTextA( hDlg, IDC_E_FORCEGSIP, g_cfg.ForceGameServerIP );
|
||||
SetDlgItemInt( hDlg, IDC_E_FORCEGSPORT, g_cfg.ForceGameServerPort, TRUE );
|
||||
|
||||
ConfigDlg_UpateEnabledControls( hDlg );
|
||||
}
|
||||
|
||||
void ConfigDlg_OnOK( HWND hDlg, BOOL bEndDialog )
|
||||
{
|
||||
// L2 version
|
||||
g_cfg.L2_version = (int)SendMessage( GetDlgItem( hDlg, IDC_CB_L2VER ), CB_GETCURSEL, 0, 0 );
|
||||
// L2 client version
|
||||
g_cfg.L2_client_version = (int)SendMessage( GetDlgItem( hDlg, IDC_CB_L2CVER ), CB_GETCURSEL, 0, 0 );
|
||||
|
||||
// full mode enable
|
||||
g_cfg.EnableModifyGameTraffic = IsDlgButtonChecked( hDlg, IDC_C_ENABLE_MODGT );
|
||||
// override game protocolversion
|
||||
g_cfg.OverrideGameProtocolVersion = (int)GetDlgItemInt( hDlg, IDC_E_OVERRIDE_GPV, NULL, TRUE );
|
||||
// thread priority raise enable
|
||||
g_cfg.ThreadProirityRaiseEnable = IsDlgButtonChecked( hDlg, IDC_C_ENABLE_THREADPRI );
|
||||
// reply L2J GameGuardQuery
|
||||
g_cfg.ReplyL2JGameGuardQuery = IsDlgButtonChecked( hDlg, IDC_C_GAMEGUARDREPLY );
|
||||
// Gracia Epilogue protocol 148 hacks
|
||||
g_cfg.GraciaEpilogueProtocol_148_hacks = IsDlgButtonChecked( hDlg, IDC_C_EPILOGUE_148_146 );
|
||||
|
||||
// L2Walker_DropRequestGMList
|
||||
g_cfg.L2Walker_DropRequestGMList = IsDlgButtonChecked( hDlg, IDC_C_L2WDROPGMLIST );
|
||||
// L2Walker_FixMoveBackwardToLocation
|
||||
g_cfg.L2Walker_FixMoveBackwardToLocation = IsDlgButtonChecked( hDlg, IDC_C_L2WMOVEFIX );
|
||||
// L2Walker_FixChangeWaitType2
|
||||
g_cfg.L2Walker_FixChangeWaitType2 = IsDlgButtonChecked( hDlg, IDC_C_L2WSITFIX );
|
||||
// L2Walker_InjectStatusUpdate
|
||||
g_cfg.L2Walker_InjectStatusUpdate = IsDlgButtonChecked( hDlg, IDC_C_L2WALKER_INJECTSTATUSUPDATE );
|
||||
// log level
|
||||
HWND h = GetDlgItem( hDlg, IDC_CB_LOGLEVEL );
|
||||
g_cfg.WarnMessageLevel = (int)SendMessage( h, CB_GETCURSEL, 0, 0 );
|
||||
|
||||
//
|
||||
// Log Game Packets
|
||||
g_cfg.LogGamePackets = IsDlgButtonChecked( hDlg, IDC_C_LOGGAMEP );
|
||||
// Log packets FileName Prefix
|
||||
GetDlgItemTextA( hDlg, IDC_E_LOGFNPREFIX, g_cfg.LogGameFileNamePrefix,
|
||||
sizeof(g_cfg.LogGameFileNamePrefix)-1 );
|
||||
// warn unknown packets
|
||||
g_cfg.WarnUnknownPacketsToStdout = IsDlgButtonChecked( hDlg, IDC_C_WARNUNKP );
|
||||
|
||||
//
|
||||
// FakeListenLoginPort
|
||||
g_cfg.FakeListenLoginPort = GetDlgItemInt( hDlg, IDC_E_FLPORT, NULL, TRUE );
|
||||
// FakeListenGamePort
|
||||
g_cfg.FakeListenGamePort = GetDlgItemInt( hDlg, IDC_E_FGPORT, NULL, TRUE );
|
||||
// RealLoginServerIP
|
||||
GetDlgItemTextA( hDlg, IDC_E_REALIP, g_cfg.RealLoginServerIP, sizeof(g_cfg.RealLoginServerIP) );
|
||||
// RealLoginServerPort
|
||||
g_cfg.RealLoginServerPort = GetDlgItemInt( hDlg, IDC_E_REALPORT, NULL, TRUE );
|
||||
// PlayGameServerNo
|
||||
//g_cfg.PlayGameServerNo = GetDlgItemInt( hDlg, IDC_E_PLAYGSNO, NULL, TRUE );
|
||||
// forced GS settings
|
||||
GetDlgItemTextA( hDlg, IDC_E_FORCEGSIP, g_cfg.ForceGameServerIP, sizeof(g_cfg.ForceGameServerIP) );
|
||||
g_cfg.ForceGameServerPort = GetDlgItemInt( hDlg, IDC_E_FORCEGSPORT, NULL, TRUE );
|
||||
|
||||
//
|
||||
g_cfg.SaveConfig();
|
||||
if( bEndDialog == TRUE ) EndDialog( hDlg, IDOK );
|
||||
}
|
||||
|
||||
void ConfigDlg_OnApply( HWND hDlg )
|
||||
{
|
||||
if( !g_plogin || !g_pgame ) return;
|
||||
// get SOME config values and save config
|
||||
ConfigDlg_OnOK( hDlg, FALSE );
|
||||
//
|
||||
// check in client is in game
|
||||
bool running = false;
|
||||
if( g_plogin )
|
||||
if( g_plogin->isRunning() ) running = true;
|
||||
if( g_pgame )
|
||||
if( g_pgame->isRunning() ) running = true;
|
||||
if( running )
|
||||
{
|
||||
log_error( LOG_WARNING, "ConfigDlg_OnApply(): warning: game is running!\n" );
|
||||
int answer = MessageBox( hDlg,
|
||||
TEXT("Warning! Listeners are running now!\n")
|
||||
TEXT("If you press 'Yes', connection will be terminated.\n")
|
||||
TEXT("If you press 'No', changes will no take effect until next connection.\n") ,
|
||||
TEXT("Warning! Game running!"), MB_YESNO | MB_ICONWARNING );
|
||||
if( answer == IDNO ) return;
|
||||
log_error( LOG_WARNING, "ConfigDlg_OnApply(): connections will be terminated.\n" );
|
||||
}
|
||||
//
|
||||
if( g_plogin ) g_plogin->signalStop(); // LoginListener may not be started in ingame mode at all
|
||||
g_pgame->signalStop();
|
||||
if( g_plogin ) // LoginListener may not be started in ingame mode at all
|
||||
{
|
||||
if( !g_plogin->waitStopped( 5000 ) )
|
||||
{
|
||||
ErrorLogger_FlushLogFile();
|
||||
MessageBox( hDlg, TEXT("Login Listener stop wait failed! Terminated..."), TEXT("Warning!"), MB_ICONWARNING );
|
||||
g_plogin->terminateThread();
|
||||
}
|
||||
} // LoginListener may not be started in ingame mode at all
|
||||
|
||||
if( !g_pgame->waitStopped( 5000 ) )
|
||||
{
|
||||
ErrorLogger_FlushLogFile();
|
||||
MessageBox( hDlg, TEXT("Game Listener stop wait failed! Terminated..."), TEXT("Warning!"), MB_ICONWARNING );
|
||||
g_pgame->terminateThread();
|
||||
}
|
||||
if( g_plogin ) // LoginListener may not be started in ingame mode at all
|
||||
{
|
||||
if( !g_plogin->start() )
|
||||
{
|
||||
ErrorLogger_FlushLogFile();
|
||||
MessageBox( hDlg, TEXT("Login Listener start failed! O_o"), TEXT("Warning!"), MB_ICONWARNING );
|
||||
}
|
||||
} // LoginListener may not be started in ingame mode at all
|
||||
|
||||
if( !g_pgame->start() )
|
||||
{
|
||||
ErrorLogger_FlushLogFile();
|
||||
MessageBox( hDlg, TEXT("Game Listener start failed! O_o"), TEXT("Warning!"), MB_ICONWARNING );
|
||||
}
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
|
||||
void ConfigDlg_UpateEnabledControls( HWND hDlg )
|
||||
{
|
||||
HWND hs, hc;
|
||||
hs = GetDlgItem( hDlg, IDC_CB_L2VER );
|
||||
hc = GetDlgItem( hDlg, IDC_CB_L2CVER );
|
||||
int srv_ver = ComboBox_GetCurSel( hs );
|
||||
int cl_ver = ComboBox_GetCurSel( hc );
|
||||
if( srv_ver == 5 && cl_ver == 5 )
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_EPILOGUE_148_146 ), TRUE );
|
||||
else
|
||||
{
|
||||
CheckDlgButton( hDlg, IDC_C_EPILOGUE_148_146, 0 );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_EPILOGUE_148_146 ), FALSE );
|
||||
}
|
||||
|
||||
// disable some controls in ingame mode
|
||||
if( g_cfg.isInGameMode == true )
|
||||
{
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_L2WMOVEFIX ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_L2WDROPGMLIST ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_L2WSITFIX ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_L2WALKER_INJECTSTATUSUPDATE ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_FLPORT ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_REALIP ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_REALPORT ), FALSE );
|
||||
//EnableWindow( GetDlgItem( hDlg, IDC_E_PLAYGSNO ), FALSE );
|
||||
}
|
||||
// also temporarily disable some controls
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_ENABLE_MODGT ), FALSE );
|
||||
}
|
||||
6
l2detect/ConfigDlg.h
Normal file
6
l2detect/ConfigDlg.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_CONFIG_DLG
|
||||
#define H_CONFIG_DLG
|
||||
|
||||
void ConfigDialogStart( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
478
l2detect/ConfigIni.cpp
Normal file
478
l2detect/ConfigIni.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
|
||||
CConfig::CConfig()
|
||||
{
|
||||
_initNull();
|
||||
}
|
||||
|
||||
CConfig::~CConfig()
|
||||
{
|
||||
_initNull();
|
||||
}
|
||||
|
||||
void CConfig::_initNull()
|
||||
{
|
||||
isInGameMode = false;
|
||||
L2_version = 0;
|
||||
L2_client_version = 0;
|
||||
//
|
||||
szCfgFileName[0] = FakeListenLoginIP[0] = FakeListenGameIP[0];
|
||||
FakeListenLoginPort = FakeListenGamePort = 0;
|
||||
// Forward connection to
|
||||
RealLoginServerIP[0] = 0;
|
||||
RealLoginServerPort = 0;
|
||||
// Catch game server traffic
|
||||
//PlayGameServerNo = 0;
|
||||
ForceGameServerIP[0] = 0;
|
||||
ForceGameServerPort = 0;
|
||||
IngameGameServerPort = 7777;
|
||||
// Logging setup
|
||||
LogGamePackets = 0;
|
||||
LogGameFileNamePrefix[0] = 0;
|
||||
WarnUnknownPacketsToStdout = DumpUnknownToStdout = WarnMessageLevel = 0;
|
||||
// hacks
|
||||
EnableModifyGameTraffic = 0; // enable or disable game protocol-level hacks
|
||||
OverrideGameProtocolVersion = 0;
|
||||
ReplyL2JGameGuardQuery = 0;
|
||||
GraciaEpilogueProtocol_148_hacks = 0;
|
||||
// L2Walker fixes
|
||||
L2Walker_DropRequestGMList = 0;
|
||||
L2Walker_FixMoveBackwardToLocation = 1;
|
||||
L2Walker_FixChangeWaitType2 = 1;
|
||||
L2Walker_InjectStatusUpdate = 0;
|
||||
// Invis GM
|
||||
InvisGMTrackEnable = 1;
|
||||
InvisGMSpeed = 400; // //gmspeed 4
|
||||
}
|
||||
|
||||
bool CConfig::ReadConfig( const wchar_t *szConfigFileName )
|
||||
{
|
||||
if( !szConfigFileName ) return false;
|
||||
char tempbuf[512] = {0};
|
||||
WideCharToMultiByte( CP_ACP, 0, szConfigFileName, -1, tempbuf, 511, NULL, NULL );
|
||||
return this->ReadConfig( tempbuf );
|
||||
}
|
||||
|
||||
bool CConfig::ReadConfig( const char *szConfigFileName )
|
||||
{
|
||||
if( !szConfigFileName ) return false;
|
||||
strcpy( this->szCfgFileName, szConfigFileName );
|
||||
FILE *f = fopen( szConfigFileName, "rt" );
|
||||
if( !f ) return false;
|
||||
|
||||
char line[512];
|
||||
size_t ll; // line length
|
||||
char *token = NULL;
|
||||
|
||||
while( !feof(f) )
|
||||
{
|
||||
memset( line, 0, sizeof(line) );
|
||||
fgets( line, sizeof(line)-1, f );
|
||||
if( line[0] == 0 ) /* line empty */ continue;
|
||||
if( (line[0] == '#') || (line[0] == ';') ) /* pass comments */ continue;
|
||||
/* remove NL & BR from end of line */
|
||||
ll = strlen( line );
|
||||
if( (line[ll-1] == '\r') || (line[ll-1] == '\n') ) line[ll-1] = 0;
|
||||
if( (line[ll-2] == '\r') || (line[ll-2] == '\n') ) line[ll-2] = 0;
|
||||
/* find '=' */
|
||||
token = strchr( line, '=' );
|
||||
if( token )
|
||||
{
|
||||
token++; // token points to next char after '='
|
||||
while( (*token) && ((*token) == ' ') ) token++; // pass spaces
|
||||
}
|
||||
else
|
||||
continue; /* no '=' symbol in line */
|
||||
/* is there any string in token */
|
||||
if( token[0] == 0 ) continue; /* token is an empty string.. */
|
||||
/* find match */
|
||||
if( strstr( line, "Lineage2Version" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->L2_version) );
|
||||
}
|
||||
if( strstr( line, "Lineage2ClientVersion" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->L2_client_version) );
|
||||
}
|
||||
if( strstr( line, "FakeListenLoginIP" ) == line )
|
||||
{
|
||||
strcpy( this->FakeListenLoginIP, token );
|
||||
}
|
||||
if( strstr( line, "FakeListenLoginPort" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->FakeListenLoginPort) );
|
||||
}
|
||||
if( strstr( line, "FakeListenGameIP" ) == line )
|
||||
{
|
||||
strcpy( this->FakeListenGameIP, token );
|
||||
}
|
||||
if( strstr( line, "FakeListenGamePort" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->FakeListenGamePort) );
|
||||
}
|
||||
if( strstr( line, "RealLoginServerIP" ) == line )
|
||||
{
|
||||
strcpy( this->RealLoginServerIP, token );
|
||||
}
|
||||
if( strstr( line, "RealLoginServerPort" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->RealLoginServerPort) );
|
||||
}
|
||||
/*if( strstr( line, "PlayGameServerNo" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->PlayGameServerNo) );
|
||||
}*/
|
||||
if( strstr( line, "ForceGameServerIP" ) == line )
|
||||
{
|
||||
strcpy( this->ForceGameServerIP, token );
|
||||
}
|
||||
if( strstr( line, "ForceGameServerPort" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->ForceGameServerPort) );
|
||||
}
|
||||
if( strstr( line, "IngameGameServerPort" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->IngameGameServerPort) );
|
||||
}
|
||||
if( strstr( line, "LogGamePackets" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->LogGamePackets) );
|
||||
}
|
||||
if( strstr( line, "LogGameFileNamePrefix" ) == line )
|
||||
{
|
||||
strcpy( this->LogGameFileNamePrefix, token );
|
||||
}
|
||||
if( strstr( line, "WarnUnknownPacketsToStdout" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->WarnUnknownPacketsToStdout) );
|
||||
}
|
||||
if( strstr( line, "DumpUnknownToStdout" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->DumpUnknownToStdout) );
|
||||
}
|
||||
if( strstr( line, "WarnMessageLevel" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->WarnMessageLevel) );
|
||||
if( WarnMessageLevel < 0 ) WarnMessageLevel = 0;
|
||||
}
|
||||
if( strstr( line, "EnableModifyGameTraffic" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->EnableModifyGameTraffic) );
|
||||
}
|
||||
if( strstr( line, "OverrideGameProtocolVersion" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->OverrideGameProtocolVersion) );
|
||||
}
|
||||
if( strstr( line, "ReplyL2JGameGuardQuery" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->ReplyL2JGameGuardQuery) );
|
||||
}
|
||||
if( strstr( line, "GraciaEpilogueProtocol_148_hacks" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->GraciaEpilogueProtocol_148_hacks) );
|
||||
}
|
||||
if( strstr( line, "ThreadProirityRaiseEnable" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->ThreadProirityRaiseEnable) );
|
||||
}
|
||||
if( strstr( line, "L2Walker_DropRequestGMList" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->L2Walker_DropRequestGMList) );
|
||||
}
|
||||
if( strstr( line, "L2Walker_FixMoveBackwardToLocation" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->L2Walker_FixMoveBackwardToLocation) );
|
||||
}
|
||||
if( strstr( line, "L2Walker_FixChangeWaitType2" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->L2Walker_FixChangeWaitType2) );
|
||||
}
|
||||
if( strstr( line, "L2Walker_InjectStatusUpdate" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->L2Walker_InjectStatusUpdate) );
|
||||
}
|
||||
if( strstr( line, "InvisGMTrackEnable" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->InvisGMTrackEnable) );
|
||||
}
|
||||
if( strstr( line, "InvisGMSpeed" ) == line )
|
||||
{
|
||||
sscanf( token, "%d", &(this->InvisGMSpeed) );
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfig::SaveConfig()
|
||||
{
|
||||
if( szCfgFileName[0] == 0 ) return false;
|
||||
FILE *f = fopen( szCfgFileName, "wt" );
|
||||
if( !f ) return false;
|
||||
|
||||
// declared in L2PcodeObfuscator.h (include L2Packets.h)
|
||||
//#define L2_VERSION_T1 0
|
||||
//#define L2_VERSION_T15 1
|
||||
//#define L2_VERSION_T2 2
|
||||
//#define L2_VERSION_T22 3
|
||||
fprintf( f, ""
|
||||
"# First - configure Lineage2 game protocol version and L2 Client version.\n"
|
||||
"# Supported versions are:\n"
|
||||
"# * Chaotic Throne 1 - The Kamael = 0\n"
|
||||
"# * Chaotic Throne 1.5 - Hellbound = 1\n"
|
||||
"# * Chaotic Throne 2 - Gracia (Part 1) = 2\n"
|
||||
"# * Chaotic Throne 2.2 - Gracia Part 2 = 3\n"
|
||||
"# * Chaotic Throne 2.3 - Gracia Final = 4\n"
|
||||
"# * Chaotic Throne 2.4 - Gracia Epilogue = 5\n"
|
||||
"# default is 4 (CT2.3 Gracia Final)\n"
|
||||
"Lineage2Version = %d\n"
|
||||
"Lineage2ClientVersion = %d\n"
|
||||
"\n\n",
|
||||
L2_version, L2_client_version );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ===============\n"
|
||||
"# Network setup \n"
|
||||
"# ===============\n"
|
||||
"\n"
|
||||
"# =======================\n"
|
||||
"# Listen ports setup \n"
|
||||
"# * Ports on which program will bind listen sockets - local address\n"
|
||||
"FakeListenLoginIP = %s\n"
|
||||
"FakeListenLoginPort = %d\n"
|
||||
"FakeListenGameIP = %s\n"
|
||||
"FakeListenGamePort = %d\n"
|
||||
"\n", FakeListenLoginIP, FakeListenLoginPort, FakeListenGameIP, FakeListenGamePort );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ========================\n"
|
||||
"# Forward connection to \n"
|
||||
"# * Where to redirect login connection - IP/hostname & port\n"
|
||||
"RealLoginServerIP = %s\n"
|
||||
"RealLoginServerPort = %d\n"
|
||||
"\n", RealLoginServerIP, RealLoginServerPort );
|
||||
|
||||
// this was removed
|
||||
/*fprintf( f, ""
|
||||
"# ===========================\n"
|
||||
"# Catch game server traffic \n"
|
||||
"# * Which Game server's IP and port will be replaced in ServerList packet\n"
|
||||
"# WARNING: this option is ignored!\n"
|
||||
"PlayGameServerNo = %d\n"
|
||||
"\n", PlayGameServerNo );*/
|
||||
|
||||
fprintf( f, "# You may force radar to redirect connection to specified game server IP:port.\n" );
|
||||
fprintf( f, "# To do this, you must set BOTH ForceGameServerIP and ForceGameServerPort.\n" );
|
||||
fprintf( f, "# if ForceGameServerIP == \"\" or ForceGameServerPort == 0 then feature is diabled.\n" );
|
||||
fprintf( f, ""
|
||||
"# ===========================\n"
|
||||
"# Force choose game server by IP:port \n"
|
||||
"# * independently of selection in server list window during login\n"
|
||||
"# * if not set (empty string) - use selected server\n"
|
||||
"ForceGameServerIP = %s\n"
|
||||
"\n", ForceGameServerIP );
|
||||
fprintf( f, ""
|
||||
"# ===========================\n"
|
||||
"# Force choose game server by IP:port \n"
|
||||
"# * independently of selection in server list window during login\n"
|
||||
"# * if = 0 - use selected server\n"
|
||||
"ForceGameServerPort = %d\n"
|
||||
"\n", ForceGameServerPort );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ===========================\n"
|
||||
"# Catch following game traffic port in INGAME mode \n"
|
||||
"IngameGameServerPort = %d\n"
|
||||
"\n", IngameGameServerPort );
|
||||
|
||||
|
||||
fprintf( f, ""
|
||||
"# =========================================================================\n"
|
||||
"# Logging Setup \n"
|
||||
"# =========================================================================\n"
|
||||
"# =========================================================================\n"
|
||||
"# Warn messages level printed to stdout \n"
|
||||
"# 0 - no messages to screen \n"
|
||||
"# 1 - errors only ( Recommended :) ) \n"
|
||||
"# 2 - errors, warnings \n"
|
||||
"# 3 - errors, warnings, AI \n"
|
||||
"# 4 - errors, warnings, AI, packet names \n"
|
||||
"# 5 - errors, warnings, AI, packet names, debug messages \n"
|
||||
"# 6 - errors, warnings, AI, packet names, debug messages, packet dumps \n"
|
||||
"# Default: 1; it cannot be <0, but can be very big number. [0..0xFFFFFFFF]\n"
|
||||
"WarnMessageLevel = %d\n"
|
||||
"\n", WarnMessageLevel );
|
||||
|
||||
fprintf( f, ""
|
||||
"# =========================================================================\n"
|
||||
"# Warn about unknown packets? 1 - yes, 0 - no; (default: 0, no) \n"
|
||||
"WarnUnknownPacketsToStdout = %d\n"
|
||||
"\n", WarnUnknownPacketsToStdout );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ==========================================================================\n"
|
||||
"# Full dump unknown packets to log? 0-no, 1-yes (Default: 0, not display)\n"
|
||||
"DumpUnknownToStdout = %d\n"
|
||||
"\n", DumpUnknownToStdout );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ====================================\n"
|
||||
"# Enable or disable logging of Game Server packets 0-disable, 1-enable (Default: 0, disable)\n"
|
||||
"LogGamePackets = %d\n"
|
||||
"\n", LogGamePackets );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ====================================\n"
|
||||
"# File name prefix for log file with game server packets log\n"
|
||||
"# (file name will look like prefix_XXXXXXXX.txt, where XXX-current date/time unix timestamp)\n"
|
||||
"# Default: prefix_\n"
|
||||
"LogGameFileNamePrefix = %s\n"
|
||||
"\n", LogGameFileNamePrefix );
|
||||
|
||||
fprintf( f, ""
|
||||
"# ==========\n"
|
||||
"# Hacks!!!! \n"
|
||||
"# ==========\n"
|
||||
" \n"
|
||||
"# ========================================\n"
|
||||
"# Enable or disable game packets modifying\n"
|
||||
"# - If disabled (0), only passive sniffing if possible, NO ANY HACKS will work\n"
|
||||
"# - If enabled (1), packet-level hacks WILL work. This setting is REQUIRED to be set to ENABLED\n"
|
||||
"# if you want any hacks to work\n"
|
||||
"# - 0-disable, 1-enable; (Default: 0, disable, passive SNIFFING ONLY)\n"
|
||||
"EnableModifyGameTraffic = %d\n"
|
||||
"\n", EnableModifyGameTraffic );
|
||||
|
||||
fprintf( f, ""
|
||||
"# !!!!! Any hacks below will not work, if EnableModifyGameTraffic is set to 0 !!!!!\n"
|
||||
"\n"
|
||||
"# =====================================================================\n"
|
||||
"# * Override game protocol version: change game protocol version number\n"
|
||||
"# * in C->S ProtocolVersion packet to given number.\n"
|
||||
"# * Value: 0 - disable this; any other number greater than 0: override to this number\n"
|
||||
"# * Default: 0\n"
|
||||
"OverrideGameProtocolVersion = %d\n"
|
||||
"# Help on protocol versions (Official server):\n"
|
||||
"# - T1 Kamael - 828\n"
|
||||
"# - T1.5 Hellbound - 831 ?\n"
|
||||
"# - T2 Gracia live - 851\n"
|
||||
"# - T2.2 Gracia Part 2 - 12-17\n"
|
||||
"# - T2.3 Gracia Final - 83-87\n"
|
||||
"# - T2.4 Gracia Epilogue - 146\n"
|
||||
"\n",
|
||||
OverrideGameProtocolVersion );
|
||||
|
||||
fprintf( f, ""
|
||||
"# If set to 1, L2Detect will send reply to standard L2J GameGuard query\n"
|
||||
"# by itself, so it will be possible to play with GameGuard disabled\n"
|
||||
"# on private servers where GameGuard is required.\n"
|
||||
"# NOTE: L2Detect will NOT reply to unknown queries! You cannot be sure in it on official servers.\n"
|
||||
"# (Default: disabled)\n"
|
||||
"ReplyL2JGameGuardQuery = %d\n"
|
||||
"\n",
|
||||
ReplyL2JGameGuardQuery );
|
||||
|
||||
fprintf( f, ""
|
||||
"# If set to 1, you know that server is using G.Epilogue protocol 148 and client\n"
|
||||
"# is using G.Epilogue protocol 146; this setting will enable protocol conversion\n"
|
||||
"# (converting some packets like ItemList, etc) between server and client, allowing\n"
|
||||
"# clent with protocol 146 to play on server with protocol 148.\n"
|
||||
"GraciaEpilogueProtocol_148_hacks = %d\n"
|
||||
"\n",
|
||||
GraciaEpilogueProtocol_148_hacks );
|
||||
|
||||
fprintf( f, ""
|
||||
"# Fixes L2Walker wrong or old packets\n"
|
||||
"L2Walker_DropRequestGMList = %d\n"
|
||||
"L2Walker_FixMoveBackwardToLocation = %d\n"
|
||||
"L2Walker_FixChangeWaitType2 = %d\n"
|
||||
"L2Walker_InjectStatusUpdate = %d\n"
|
||||
"\n",
|
||||
L2Walker_DropRequestGMList,
|
||||
L2Walker_FixMoveBackwardToLocation,
|
||||
L2Walker_FixChangeWaitType2,
|
||||
L2Walker_InjectStatusUpdate );
|
||||
|
||||
fprintf( f, ""
|
||||
"# Enable/disable game listener thread priority above normal. Try changing this, if you have comp. lags...\n"
|
||||
"# default: 0, disabled\n"
|
||||
"ThreadProirityRaiseEnable = %d\n"
|
||||
"\n",
|
||||
ThreadProirityRaiseEnable );
|
||||
|
||||
|
||||
fprintf( f, ""
|
||||
"# Enable/disable invisible GM tracking\n"
|
||||
"# default: 1, enabled\n"
|
||||
"InvisGMTrackEnable = %d\n"
|
||||
"\n",
|
||||
InvisGMTrackEnable );
|
||||
|
||||
fprintf( f, ""
|
||||
"# Invisible GM display speed\n"
|
||||
"# default: 400, as //gmspeed 4\n"
|
||||
"InvisGMSpeed = %d\n"
|
||||
"\n",
|
||||
InvisGMSpeed );
|
||||
|
||||
|
||||
fclose( f );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CConfig::SetDefault()
|
||||
{
|
||||
// declared in L2PcodeObfuscator.h (include L2Packets.h)
|
||||
//#define L2_VERSION_T1 0
|
||||
//#define L2_VERSION_T15 1
|
||||
//#define L2_VERSION_T2 2
|
||||
//#define L2_VERSION_T22 3
|
||||
L2_version = 4;
|
||||
L2_client_version = 4;
|
||||
|
||||
// Listen port setup
|
||||
strcpy( FakeListenLoginIP, "127.0.0.1" );
|
||||
FakeListenLoginPort = 9998;
|
||||
strcpy( FakeListenGameIP, "127.0.0.1" );
|
||||
FakeListenGamePort = 9999;
|
||||
|
||||
// Forward connection to
|
||||
strcpy( RealLoginServerIP, "0.0.0.0" );
|
||||
RealLoginServerPort = 2106;
|
||||
|
||||
// Catch game server traffic
|
||||
//PlayGameServerNo = 0;
|
||||
ForceGameServerIP[0] = 0;
|
||||
ForceGameServerPort = 0;
|
||||
IngameGameServerPort = 7777;
|
||||
|
||||
// Logging setup
|
||||
LogGamePackets = 0;
|
||||
LogGameFileNamePrefix[0] = 0;
|
||||
WarnUnknownPacketsToStdout = 0;
|
||||
DumpUnknownToStdout = 0;
|
||||
WarnMessageLevel = 4;
|
||||
|
||||
// hacks
|
||||
EnableModifyGameTraffic = 0; // enable or disable game protocol-level hacks
|
||||
OverrideGameProtocolVersion = 0;
|
||||
ReplyL2JGameGuardQuery = 0;
|
||||
GraciaEpilogueProtocol_148_hacks = 0;
|
||||
|
||||
// L2Walker fixes
|
||||
L2Walker_DropRequestGMList = 0;
|
||||
L2Walker_FixMoveBackwardToLocation = 1;
|
||||
L2Walker_FixChangeWaitType2 = 1;
|
||||
L2Walker_InjectStatusUpdate = 0;
|
||||
|
||||
// tweaks
|
||||
ThreadProirityRaiseEnable = 1;
|
||||
|
||||
// Invis GM
|
||||
InvisGMTrackEnable = 0;
|
||||
InvisGMSpeed = 400; // //gmspeed 4
|
||||
}
|
||||
69
l2detect/ConfigIni.h
Normal file
69
l2detect/ConfigIni.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef CONFIGINI_H_
|
||||
#define CONFIGINI_H_
|
||||
|
||||
class CConfig
|
||||
{
|
||||
public:
|
||||
CConfig();
|
||||
virtual ~CConfig();
|
||||
|
||||
public:
|
||||
bool ReadConfig( const char *szConfigFileName );
|
||||
bool ReadConfig( const wchar_t *szConfigFilename );
|
||||
bool SaveConfig();
|
||||
void SetDefault();
|
||||
|
||||
protected:
|
||||
void _initNull();
|
||||
|
||||
public:
|
||||
char szCfgFileName[256];
|
||||
bool isInGameMode;
|
||||
|
||||
int L2_version;
|
||||
int L2_client_version;
|
||||
|
||||
// Listen port setup
|
||||
char FakeListenLoginIP[32];
|
||||
int FakeListenLoginPort;
|
||||
char FakeListenGameIP[32];
|
||||
int FakeListenGamePort;
|
||||
|
||||
// Forward connection to
|
||||
char RealLoginServerIP[128];
|
||||
int RealLoginServerPort;
|
||||
|
||||
// Catch game server traffic
|
||||
//int PlayGameServerNo; // removed!
|
||||
char ForceGameServerIP[32];
|
||||
int ForceGameServerPort;
|
||||
int IngameGameServerPort;
|
||||
|
||||
// Logging setup
|
||||
int LogGamePackets;
|
||||
char LogGameFileNamePrefix[128];
|
||||
int WarnUnknownPacketsToStdout;
|
||||
int DumpUnknownToStdout;
|
||||
int WarnMessageLevel;
|
||||
|
||||
// hacks
|
||||
int EnableModifyGameTraffic; // enable or disable game protocol-level hacks
|
||||
int OverrideGameProtocolVersion;
|
||||
int ReplyL2JGameGuardQuery;
|
||||
int GraciaEpilogueProtocol_148_hacks;
|
||||
|
||||
// L2Walker fixes
|
||||
int L2Walker_DropRequestGMList;
|
||||
int L2Walker_FixMoveBackwardToLocation;
|
||||
int L2Walker_FixChangeWaitType2;
|
||||
int L2Walker_InjectStatusUpdate;
|
||||
|
||||
// tweaks
|
||||
int ThreadProirityRaiseEnable;
|
||||
|
||||
// invis GM detection
|
||||
int InvisGMTrackEnable;
|
||||
int InvisGMSpeed;
|
||||
};
|
||||
|
||||
#endif /* CONFIGINI_H_ */
|
||||
407
l2detect/DebugDlg.cpp
Normal file
407
l2detect/DebugDlg.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "DebugDlg.h"
|
||||
#include "ConfigDlg.h"
|
||||
|
||||
#include "Logger.h"
|
||||
#include "LoginListener.h"
|
||||
#include "GameListener.h"
|
||||
#include "GameClient.h"
|
||||
|
||||
#include "net_hook.h"
|
||||
|
||||
// EXTERNALS
|
||||
// global app configuration
|
||||
extern class CConfig g_cfg; // in main.cpp
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
// global listeners
|
||||
extern class LoginListener *g_plogin;
|
||||
extern class GameListener *g_pgame;
|
||||
|
||||
#define TIMER_UPDATEINFO 1
|
||||
|
||||
BOOL DebugDlg_OnInitDialog( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedRunconfig( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedStartLL( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedStartGL( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedStopLL( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedStopGL( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedFlushLog( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedEnableConsole( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedDisableConsole( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedLoadWalker( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedUnloadWalker( HWND hDlg );
|
||||
void DebugDlg_OnTimer( HWND hDlg, UINT_PTR nIDEvent );
|
||||
void DebugDlg_updateInfo( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedValidateInterception( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedInterceptConnect( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedCheckVP( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedDumpAllRelations( HWND hDlg );
|
||||
void DebugDlg_OnBnClickedPrintAddrTid( HWND hDlg );
|
||||
|
||||
|
||||
INT_PTR CALLBACK DebugDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: DebugDlg_OnInitDialog( hDlg ); break;
|
||||
case WM_TIMER: DebugDlg_OnTimer( hDlg, (UINT_PTR)wParam ); break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
//case IDC_RUNCONFIG: DebugDlg_OnBnClickedRunconfig( hDlg ); break;
|
||||
case IDC_STARTLL: DebugDlg_OnBnClickedStartLL( hDlg ); break;
|
||||
case IDC_STOPLL: DebugDlg_OnBnClickedStopLL( hDlg ); break;
|
||||
case IDC_STARTGL: DebugDlg_OnBnClickedStartGL( hDlg ); break;
|
||||
case IDC_STOPGL: DebugDlg_OnBnClickedStopGL( hDlg ); break;
|
||||
case IDC_FLUSH_LOG: DebugDlg_OnBnClickedFlushLog( hDlg ); break;
|
||||
case IDC_B_CONENABLE: DebugDlg_OnBnClickedEnableConsole( hDlg ); break;
|
||||
case IDC_B_CONDISABLE: DebugDlg_OnBnClickedDisableConsole( hDlg ); break;
|
||||
case IDC_B_VALIDATEINTERCEPT: DebugDlg_OnBnClickedValidateInterception( hDlg ); break;
|
||||
case IDC_B_INTERCEPTCONNECT: DebugDlg_OnBnClickedInterceptConnect( hDlg ); break;
|
||||
case IDC_B_CHECK_VIRTUALPROTECTEX: DebugDlg_OnBnClickedCheckVP( hDlg ); break;
|
||||
case IDC_B_LOADWALKER: DebugDlg_OnBnClickedLoadWalker( hDlg ); break;
|
||||
case IDC_B_UNLOADWALKER: DebugDlg_OnBnClickedUnloadWalker( hDlg ); break;
|
||||
case IDC_B_DUMP_ALL_RELATIONS: DebugDlg_OnBnClickedDumpAllRelations( hDlg ); break;
|
||||
case IDC_B_PRINTADDRTID: DebugDlg_OnBnClickedPrintAddrTid( hDlg ); break;
|
||||
case IDOK: EndDialog( hDlg, IDOK ); break;
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DebugDialogStart( HWND hWndParent, HINSTANCE hInst )
|
||||
{
|
||||
DialogBoxParam( hInst, MAKEINTRESOURCE(IDD_DEBUG), hWndParent, DebugDlgProc, NULL );
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DebugDlg
|
||||
BOOL DebugDlg_OnInitDialog( HWND hDlg )
|
||||
{
|
||||
DebugDlg_updateInfo( hDlg );
|
||||
SetTimer( hDlg, TIMER_UPDATEINFO, 1000, NULL );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//void DebugDlg_OnBnClickedRunconfig( HWND hDlg )
|
||||
//{
|
||||
// ConfigDialogStart( hDlg, g_radardll_hinst );
|
||||
//}
|
||||
|
||||
void DebugDlg_OnBnClickedStartLL( HWND hDlg )
|
||||
{
|
||||
if( g_plogin )
|
||||
{
|
||||
if( g_plogin->isRunning() )
|
||||
{
|
||||
MessageBox( hDlg, TEXT("Login listener already running!"), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
return;
|
||||
}
|
||||
if( !g_plogin->start() )
|
||||
MessageBox( hDlg, TEXT("Login listener start failed!"), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedStartGL( HWND hDlg )
|
||||
{
|
||||
if( g_pgame )
|
||||
{
|
||||
if( g_pgame->isRunning() )
|
||||
{
|
||||
MessageBox( hDlg, TEXT("Game listener already running!"), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
return;
|
||||
}
|
||||
if( !g_pgame->start() )
|
||||
MessageBox( hDlg, TEXT("Game listener start failed!"), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedStopLL( HWND hDlg )
|
||||
{
|
||||
if( g_plogin )
|
||||
{
|
||||
if( !g_plogin->isRunning() )
|
||||
{
|
||||
MessageBox( hDlg, TEXT("Login listener already stopped!"), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
return;
|
||||
}
|
||||
g_plogin->signalStop();
|
||||
// wait 10 secs to stop
|
||||
if( !g_plogin->waitStopped( 10000 ) )
|
||||
{
|
||||
g_plogin->terminateThread();
|
||||
MessageBox( hDlg, TEXT("Login listener stop wait failed, terminated :("), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedStopGL( HWND hDlg )
|
||||
{
|
||||
if( g_pgame )
|
||||
{
|
||||
if( !g_pgame->isRunning() )
|
||||
{
|
||||
MessageBox( hDlg, TEXT("Game listener already stopped!"), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
return;
|
||||
}
|
||||
g_pgame->signalStop();
|
||||
// wait 10 secs to stop
|
||||
if( !g_pgame->waitStopped( 10000 ) )
|
||||
{
|
||||
g_pgame->terminateThread();
|
||||
MessageBox( hDlg, TEXT("Game listener stop wait failed, terminated :("), TEXT("Ops!"), MB_ICONINFORMATION );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedEnableConsole( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
ErrorLogger_EnableLoggingToConsole( true );
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedDisableConsole( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
ErrorLogger_EnableLoggingToConsole( false );
|
||||
}
|
||||
|
||||
void DebugDlg_OnTimer( HWND hDlg, UINT_PTR nIDEvent )
|
||||
{
|
||||
if( nIDEvent == TIMER_UPDATEINFO )
|
||||
{
|
||||
DebugDlg_updateInfo( hDlg );
|
||||
}
|
||||
}
|
||||
|
||||
void DebugDlg_updateInfo( HWND hDlg )
|
||||
{
|
||||
int run;
|
||||
HWND hWndB;
|
||||
// update LoginListener info
|
||||
// LoginListener may not be started in ingame mode at all
|
||||
if( g_plogin )
|
||||
{
|
||||
run = g_plogin->isRunning();
|
||||
if( run )
|
||||
{
|
||||
SetDlgItemText( hDlg, IDC_ELLSTATUS, TEXT("ON") );
|
||||
// start button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STARTLL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
// stop button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STOPLL );
|
||||
if( hWndB ) EnableWindow( hWndB, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetDlgItemText( hDlg, IDC_ELLSTATUS, TEXT("Off") );
|
||||
// start button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STARTLL );
|
||||
if( hWndB ) EnableWindow( hWndB, TRUE );
|
||||
// stop button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STOPLL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
}
|
||||
}
|
||||
else // all start & stop LL buttons disabled
|
||||
{
|
||||
// start button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STARTLL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
// stop button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STOPLL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
}
|
||||
|
||||
// update GameListener info
|
||||
if( g_pgame )
|
||||
{
|
||||
run = g_pgame->isRunning();
|
||||
if( run )
|
||||
{
|
||||
SetDlgItemText( hDlg, IDC_EGLSTATUS, TEXT("ON") );
|
||||
// start button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STARTGL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
// stop button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STOPGL );
|
||||
if( hWndB ) EnableWindow( hWndB, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetDlgItemText( hDlg, IDC_EGLSTATUS, TEXT("Off") );
|
||||
// start button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STARTGL );
|
||||
if( hWndB ) EnableWindow( hWndB, TRUE );
|
||||
// stop button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STOPGL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
}
|
||||
}
|
||||
else // all start & stop GL buttons disabled
|
||||
{
|
||||
// start button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STARTGL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
// stop button
|
||||
hWndB = GetDlgItem( hDlg, IDC_STOPGL );
|
||||
if( hWndB ) EnableWindow( hWndB, FALSE );
|
||||
}
|
||||
|
||||
if( g_game_client->getState() == GCST_IN_GAME )
|
||||
{
|
||||
TCHAR tstr[256];
|
||||
// hp
|
||||
wsprintf( tstr, _T("%d / %d"), g_game_client->ai.usr.hp, g_game_client->ai.usr.hp_max );
|
||||
SetDlgItemText( hDlg, IDC_HP, tstr );
|
||||
// mp
|
||||
wsprintf( tstr, _T("%d / %d"), g_game_client->ai.usr.mp, g_game_client->ai.usr.mp_max );
|
||||
SetDlgItemText( hDlg, IDC_MP, tstr );
|
||||
// cp
|
||||
wsprintf( tstr, _T("%d / %d"), g_game_client->ai.usr.cp, g_game_client->ai.usr.cp_max );
|
||||
SetDlgItemText( hDlg, IDC_CP, tstr );
|
||||
// char name
|
||||
wsprintf( tstr, _T("%s (tit %s), Lv %d (%s/base %s)"),
|
||||
g_game_client->ai.usr.charName, g_game_client->ai.usr.charTitle,
|
||||
g_game_client->ai.usr.level,
|
||||
g_game_client->ai.usr.getClassStr(), g_game_client->ai.usr.getBaseClassStr() );
|
||||
SetDlgItemText( hDlg, IDC_CHARNAME, tstr );
|
||||
}
|
||||
else SetDlgItemText( hDlg, IDC_CHARNAME, TEXT("<Not in game!>") );
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedFlushLog( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER( hDlg );
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedValidateInterception( HWND hDlg )
|
||||
{
|
||||
hDlg = NULL;
|
||||
Hook_ValidateInterception_my();
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedInterceptConnect( HWND hDlg )
|
||||
{
|
||||
hDlg = NULL;
|
||||
Hook_InterceptConnect_my();
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedCheckVP( HWND hDlg )
|
||||
{
|
||||
hDlg = NULL;
|
||||
Hook_CheckVirtualProtect();
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedLoadWalker( HWND hDlg )
|
||||
{
|
||||
HINSTANCE hDllL2Walker = GetModuleHandle( TEXT("L2Walker.dll") );
|
||||
TCHAR text[256];
|
||||
if( hDllL2Walker != NULL )
|
||||
{
|
||||
log_error( LOG_OK, "L2Walker.dll already loaded at 0x%p\n", (void *)hDllL2Walker );
|
||||
wsprintf( text, TEXT("L2Walker.dll already loaded at 0x%p"), (void *)hDllL2Walker );
|
||||
MessageBox( hDlg, text, TEXT("Cannot!"), MB_ICONWARNING );
|
||||
return;
|
||||
}
|
||||
hDllL2Walker = LoadLibrary( TEXT("L2Walker.dll") );
|
||||
if( !hDllL2Walker )
|
||||
{
|
||||
ErrorLogger_LogLastError( "LoadLibrary l2walker", GetLastError() );
|
||||
MessageBox( hDlg, TEXT("Cannot load L2Walker.dll!\nError is in log."), TEXT("Cannot!"), MB_ICONSTOP );
|
||||
return;
|
||||
}
|
||||
log_error( LOG_OK, "L2Walker.dll loaded at 0x%p\n", (void *)hDllL2Walker );
|
||||
ErrorLogger_FlushLogFile();
|
||||
// RVA 000196E0
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedUnloadWalker( HWND hDlg )
|
||||
{
|
||||
HINSTANCE hDllL2Walker = GetModuleHandle( TEXT("L2Walker.dll") );
|
||||
if( hDllL2Walker == NULL )
|
||||
{
|
||||
MessageBox( hDlg, TEXT("L2Walker.dll not loaded!"), TEXT("Cannot!"), MB_ICONWARNING );
|
||||
return;
|
||||
}
|
||||
log_error( LOG_DEBUG, "FreeLibrary() for L2Walker.dll...\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
FreeLibrary( hDllL2Walker );
|
||||
log_error( LOG_OK, "L2Walker.dll unloaded.\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
|
||||
void str_relation( wchar_t *out, unsigned int relation )
|
||||
{
|
||||
out[0] = 0;
|
||||
const unsigned int RELATION_PARTY1 = 0x00001; // party member
|
||||
const unsigned int RELATION_PARTY2 = 0x00002; // party member
|
||||
const unsigned int RELATION_PARTY3 = 0x00004; // party member
|
||||
const unsigned int RELATION_PARTY4 = 0x00008; // party member (for information, see L2PcInstance.getRelation())
|
||||
const unsigned int RELATION_PARTYLEADER = 0x00010; // true if is party leader
|
||||
const unsigned int RELATION_HAS_PARTY = 0x00020; // true if is in party
|
||||
const unsigned int RELATION_CLAN_MEMBER = 0x00040; // true if is in clan
|
||||
const unsigned int RELATION_LEADER = 0x00080; // true if is clan leader
|
||||
const unsigned int RELATION_CLAN_MATE = 0x00100; // true if is in same clan
|
||||
const unsigned int RELATION_INSIEGE = 0x00200; // true if in siege
|
||||
const unsigned int RELATION_ATTACKER = 0x00400; // true when attacker
|
||||
const unsigned int RELATION_ALLY = 0x00800; // blue siege icon, cannot have if red
|
||||
const unsigned int RELATION_ENEMY = 0x01000; // true when red icon, doesn't matter with blue
|
||||
const unsigned int RELATION_1SIDED_WAR = 0x08000; // single fist
|
||||
const unsigned int RELATION_MUTUAL_WAR = 0x04000; // double fist
|
||||
const unsigned int RELATION_ALLY_MEMBER = 0x10000; // clan is in alliance
|
||||
const unsigned int RELATION_TERRITORY_WAR= 0x80000; // show Territory War icon
|
||||
if( relation & RELATION_PARTY1 ) wcscat( out, L"RELATION_PARTY1 " );
|
||||
if( relation & RELATION_PARTY2 ) wcscat( out, L"RELATION_PARTY2 " );
|
||||
if( relation & RELATION_PARTY3 ) wcscat( out, L"RELATION_PARTY3 " );
|
||||
if( relation & RELATION_PARTY4 ) wcscat( out, L"RELATION_PARTY4 " );
|
||||
if( relation & RELATION_PARTYLEADER ) wcscat( out, L"RELATION_PARTYLEADER " );
|
||||
if( relation & RELATION_HAS_PARTY ) wcscat( out, L"RELATION_HAS_PARTY " );
|
||||
if( relation & RELATION_CLAN_MEMBER ) wcscat( out, L"RELATION_CLAN_MEMBER " );
|
||||
if( relation & RELATION_LEADER ) wcscat( out, L"RELATION_LEADER " );
|
||||
if( relation & RELATION_CLAN_MATE ) wcscat( out, L"RELATION_CLAN_MATE " );
|
||||
if( relation & RELATION_INSIEGE ) wcscat( out, L"RELATION_INSIEGE " );
|
||||
if( relation & RELATION_ATTACKER ) wcscat( out, L"RELATION_ATTACKER " );
|
||||
if( relation & RELATION_ALLY ) wcscat( out, L"RELATION_ALLY " );
|
||||
if( relation & RELATION_ENEMY ) wcscat( out, L"RELATION_ENEMY " );
|
||||
if( relation & RELATION_1SIDED_WAR ) wcscat( out, L"RELATION_1SIDED_WAR " );
|
||||
if( relation & RELATION_MUTUAL_WAR ) wcscat( out, L"RELATION_MUTUAL_WAR " );
|
||||
if( relation & RELATION_ALLY_MEMBER ) wcscat( out, L"RELATION_ALLY_MEMBER " );
|
||||
if( relation & RELATION_TERRITORY_WAR ) wcscat( out, L"RELATION_TERRITORY_WAR " );
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedDumpAllRelations( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER( hDlg );
|
||||
CharArray_Lock();
|
||||
int i;
|
||||
FILE *f = fopen( "Relations.txt", "at" );
|
||||
fwprintf( f, L"User: [%s] 0x%08X\n", g_game_client->ai.usr.charName, g_game_client->ai.usr.relation );
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
if( !chars_array[i] ) continue;
|
||||
if( chars_array[i]->isUnused() ) continue;
|
||||
wchar_t rel[512] = {0};
|
||||
str_relation( rel, chars_array[i]->relation );
|
||||
fwprintf( f, L"Char[%d]: [%s] 0x%08X [%s]\n", i, chars_array[i]->charName, chars_array[i]->relation, rel );
|
||||
}
|
||||
fprintf( f, "====== END =====\n" );
|
||||
fclose( f );
|
||||
CharArray_Unlock();
|
||||
}
|
||||
|
||||
void DebugDlg_OnBnClickedPrintAddrTid( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER( hDlg );
|
||||
void *addr = (void *)&(g_game_client->ai.dwThreadID);
|
||||
log_error( LOG_OK, "&(g_game_client->ai.dwThreadID) = 0x%p\n", addr );
|
||||
}
|
||||
6
l2detect/DebugDlg.h
Normal file
6
l2detect/DebugDlg.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_DEBUG_DLG
|
||||
#define H_DEBUG_DLG
|
||||
|
||||
void DebugDialogStart( HWND hWndParent, HINSTANCE hInst );
|
||||
|
||||
#endif
|
||||
77
l2detect/DistPri.cpp
Normal file
77
l2detect/DistPri.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "stdafx.h"
|
||||
#include "DistPri.h"
|
||||
|
||||
DistancePriorities::DistancePriorities()
|
||||
{
|
||||
removeAll();
|
||||
}
|
||||
|
||||
DistancePriorities::~DistancePriorities()
|
||||
{
|
||||
removeAll();
|
||||
}
|
||||
|
||||
int DistancePriorities::getPriorityForDistance( double dist ) const
|
||||
{
|
||||
if( dist > 10000.0 ) return 0; // too far
|
||||
int idist = (int)dist, i=0, last_pri_mod = -1;
|
||||
for( i=0; i<MAXN; i++ )
|
||||
{
|
||||
if( (m_min[i] >= 0) && (m_max[i] >= 0) )
|
||||
{
|
||||
last_pri_mod = m_pri_mod[i]; // remember last priority modifier
|
||||
if( (m_min[i] <= idist) && (idist < m_max[i]) )
|
||||
return m_pri_mod[i];
|
||||
}
|
||||
}
|
||||
// if we still here, no range found for dist
|
||||
// return latest priority from list
|
||||
return last_pri_mod;
|
||||
}
|
||||
|
||||
void DistancePriorities::removeAll()
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<MAXN; i++ )
|
||||
{
|
||||
m_min[i] = m_max[i] = -1;
|
||||
m_pri_mod[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int DistancePriorities::addRangePri( int min, int max, int pri_mod )
|
||||
{
|
||||
if( min<0 || max<=min ) return -1; // invalid parameters
|
||||
int i=0, idx = -1;
|
||||
for( i=0; i<MAXN; i++ )
|
||||
{
|
||||
if( m_min[i] == -1 )
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( idx == -1 ) return -1;
|
||||
m_min[idx] = min;
|
||||
m_max[idx] = max;
|
||||
m_pri_mod[idx] = pri_mod;
|
||||
return idx;
|
||||
}
|
||||
|
||||
void DistancePriorities::initDefaultPriorities()
|
||||
{
|
||||
removeAll();
|
||||
addRangePri( 0, 400, 50 ); // [0 .. 400)
|
||||
addRangePri( 400, 600, 30 ); // [400 .. 600)
|
||||
addRangePri( 600, 1000, 10 ); // [600 .. 1000)
|
||||
}
|
||||
|
||||
void DistancePriorities::getRangeInfo( int range_idx, int *min, int *max, int *pri_mod )
|
||||
{
|
||||
if( (range_idx>=0) && (range_idx<MAXN) )
|
||||
{
|
||||
if( min ) (*min) = m_min[range_idx];
|
||||
if( max ) (*max) = m_max[range_idx];
|
||||
if( pri_mod ) (*pri_mod) = m_pri_mod[range_idx];
|
||||
}
|
||||
}
|
||||
22
l2detect/DistPri.h
Normal file
22
l2detect/DistPri.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
class DistancePriorities
|
||||
{
|
||||
public:
|
||||
static const int MAXN = 10; // maximum of 10 ranges
|
||||
public:
|
||||
DistancePriorities();
|
||||
~DistancePriorities();
|
||||
|
||||
public:
|
||||
void initDefaultPriorities();
|
||||
void removeAll();
|
||||
int getPriorityForDistance( double dist ) const;
|
||||
int addRangePri( int min, int max, int pri_mod );
|
||||
void getRangeInfo( int range_idx, int *min, int *max, int *pri_mod );
|
||||
|
||||
protected:
|
||||
int m_min[MAXN];
|
||||
int m_max[MAXN];
|
||||
int m_pri_mod[MAXN];
|
||||
};
|
||||
49
l2detect/DlgPressKey.cpp
Normal file
49
l2detect/DlgPressKey.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
|
||||
int g_dlgpk_vkey = 0;
|
||||
HWND g_dlgpk_hdlg = NULL;
|
||||
WNDPROC g_dlgpk_oldproc = NULL;
|
||||
|
||||
LRESULT CALLBACK DlgPressKey_StaticDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if( uMsg == WM_KEYUP )
|
||||
{
|
||||
g_dlgpk_vkey = (int)wParam;
|
||||
PostMessage( g_dlgpk_hdlg, WM_CLOSE, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
return CallWindowProc( g_dlgpk_oldproc, hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK DlgPressKey_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HWND hwndSt = NULL; wParam; lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
g_dlgpk_vkey = 0;
|
||||
g_dlgpk_hdlg = hDlg;
|
||||
hwndSt = GetDlgItem( hDlg, IDC_APPLY );
|
||||
g_dlgpk_oldproc = (WNDPROC)(void *)(LONG_PTR)GetWindowLongPtr( hwndSt, GWLP_WNDPROC );
|
||||
SetWindowLongPtr( hwndSt, GWLP_WNDPROC, (LONG_PTR)(void *)DlgPressKey_StaticDlgProc );
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
if( g_dlgpk_vkey == 0 )EndDialog( hDlg, IDCANCEL );
|
||||
else EndDialog( hDlg, IDOK );
|
||||
break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int DlgPressKey_InputPressKey( HWND hWndParent )
|
||||
{
|
||||
g_dlgpk_vkey = 0;
|
||||
INT_PTR ret = DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_PRESSKEY),
|
||||
hWndParent, DlgPressKey_DlgProc, 0 );
|
||||
if( ret == IDCANCEL ) return 0;
|
||||
return g_dlgpk_vkey;
|
||||
}
|
||||
3
l2detect/DlgPressKey.h
Normal file
3
l2detect/DlgPressKey.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
int DlgPressKey_InputPressKey( HWND hWndParent );
|
||||
163
l2detect/Dlg_FindInDB.cpp
Normal file
163
l2detect/Dlg_FindInDB.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "stdafx.h"
|
||||
#include "Dlg_FindInDB.h"
|
||||
#include "Resource.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
|
||||
Dlg_FindInDB::Dlg_FindInDB( MODE mode )
|
||||
{
|
||||
m_mode = mode;
|
||||
itemID = 0;
|
||||
itemName[0] = 0;
|
||||
itemNameW[0] = 0;
|
||||
}
|
||||
|
||||
Dlg_FindInDB::~Dlg_FindInDB()
|
||||
{
|
||||
itemID = 0;
|
||||
itemName[0] = 0;
|
||||
itemNameW[0] = 0;
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK Dlg_FindInDB_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
bool Dlg_FindInDB::runDialog( HWND hWndParent )
|
||||
{
|
||||
INT_PTR ret = DialogBoxParam( g_radardll_hinst,
|
||||
MAKEINTRESOURCE(IDD_SR_FINDINDB), hWndParent, Dlg_FindInDB_Proc, (LPARAM)this );
|
||||
if( ret == IDOK ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Dlg_FindInDB_OnInitDialog( HWND hDlg, LPARAM lParam );
|
||||
void Dlg_FindInDB_OnOK( HWND hDlg );
|
||||
void Dlg_FindInDB_OnFind( HWND hDlg );
|
||||
|
||||
INT_PTR CALLBACK Dlg_FindInDB_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: Dlg_FindInDB_OnInitDialog( hDlg, lParam ); break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
case IDOK: Dlg_FindInDB_OnOK( hDlg ); break;
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
case IDC_FIND: Dlg_FindInDB_OnFind( hDlg ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Dlg_FindInDB_OnInitDialog( HWND hDlg, LPARAM lParam )
|
||||
{
|
||||
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
|
||||
class Dlg_FindInDB *cls = (class Dlg_FindInDB *)lParam;
|
||||
switch( cls->getMode() )
|
||||
{
|
||||
case Dlg_FindInDB::MODE_ITEM:
|
||||
{
|
||||
SetWindowText( hDlg, TEXT("Find item in DB") );
|
||||
} break;
|
||||
case Dlg_FindInDB::MODE_NPC:
|
||||
{
|
||||
SetWindowText( hDlg, TEXT("Find NPC in DB") );
|
||||
} break;
|
||||
case Dlg_FindInDB::NODE_SKILL:
|
||||
{
|
||||
SetWindowText( hDlg, TEXT("Find skill in DB") );
|
||||
} break;
|
||||
}
|
||||
CheckDlgButton( hDlg, IDC_R_CONTAINS, BST_CHECKED );
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
DWORD dwLvExStyle = LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
|
||||
SendMessage( hwndLV, LVM_SETEXTENDEDLISTVIEWSTYLE, (WPARAM)dwLvExStyle, (LPARAM)dwLvExStyle );
|
||||
TCHAR text[256] = {0};
|
||||
LVCOLUMN lvc;
|
||||
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
||||
lvc.fmt = LVCFMT_LEFT;
|
||||
lvc.cx = 60;
|
||||
lvc.iSubItem = 0;
|
||||
lvc.pszText = text;
|
||||
lstrcpy( text, TEXT("id") );
|
||||
ListView_InsertColumn( hwndLV, 0, &lvc );
|
||||
lvc.cx = 200;
|
||||
lvc.iSubItem = 1;
|
||||
lstrcpy( text, TEXT("name") );
|
||||
ListView_InsertColumn( hwndLV, 1, &lvc );
|
||||
}
|
||||
|
||||
void Dlg_FindInDB_OnOK( HWND hDlg )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
int iSel = ListView_GetNextItem( hwndLV, -1, LVNI_SELECTED );
|
||||
if( iSel == -1 ) return;
|
||||
class Dlg_FindInDB *cls = (class Dlg_FindInDB *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||||
if( !cls ) return;
|
||||
TCHAR text[256];
|
||||
LVITEM lvi;
|
||||
lvi.iItem = iSel;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.pszText = text;
|
||||
lvi.cchTextMax = 255;
|
||||
ListView_GetItem( hwndLV, &lvi );
|
||||
_stscanf( lvi.pszText, _T("%d"), &(cls->itemID) );
|
||||
lvi.iSubItem = 1;
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.pszText = text;
|
||||
lvi.cchTextMax = 255;
|
||||
ListView_GetItem( hwndLV, &lvi );
|
||||
#ifdef UNICODE
|
||||
wcscpy( cls->itemNameW, lvi.pszText );
|
||||
sprintf( cls->itemName, "%S", lvi.pszText );
|
||||
#else
|
||||
strcpy( cls->itemName, lvi.pszText );
|
||||
wsprintfW( cls->itemNameW, L"%S", lvi.pszText );
|
||||
#endif
|
||||
EndDialog( hDlg, IDOK );
|
||||
}
|
||||
|
||||
void Dlg_FindInDB_OnFind( HWND hDlg )
|
||||
{
|
||||
TCHAR text[256] = {0};
|
||||
char toFind[256] = {0};
|
||||
char queryString[256] = {0};
|
||||
GetDlgItemTextA( hDlg, IDC_EDITNAME, toFind, 255 );
|
||||
toFind[255] = 0;
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
int starts_with = IsDlgButtonChecked( hDlg, IDC_R_STWITH );
|
||||
int contains = IsDlgButtonChecked( hDlg, IDC_R_CONTAINS );
|
||||
int ends_with = IsDlgButtonChecked( hDlg, IDC_R_ENWITH );
|
||||
if( contains ) sprintf( queryString, "%%%s%%", toFind );
|
||||
if( ends_with ) sprintf( queryString, "%%%s", toFind );
|
||||
if( starts_with ) sprintf( queryString, "%s%%", toFind );
|
||||
L2Data_DB_Result res;
|
||||
res.inMaxRowsToGet = 32;
|
||||
if( L2Data_DB_Query_Items_ByName( queryString, &res ) )
|
||||
{
|
||||
ListView_DeleteAllItems( hwndLV );
|
||||
int nr = res.rowCount;
|
||||
int i;
|
||||
for( i=0; i<nr; i++ )
|
||||
{
|
||||
LVITEM lvi;
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = 999;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = text;
|
||||
wsprintf( text, TEXT("%S"), res.rows[i][0] );
|
||||
int added_item = ListView_InsertItem( hwndLV, &lvi );
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 1;
|
||||
lvi.pszText = text;
|
||||
wsprintf( text, TEXT("%S"), res.rows[i][1] );
|
||||
ListView_SetItem( hwndLV, &lvi );
|
||||
}
|
||||
L2Data_DB_Free_Result( &res );
|
||||
}
|
||||
}
|
||||
31
l2detect/Dlg_FindInDB.h
Normal file
31
l2detect/Dlg_FindInDB.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef H_DLG_FINDINDB
|
||||
#define H_DLG_FINDINDB
|
||||
|
||||
class Dlg_FindInDB
|
||||
{
|
||||
public:
|
||||
typedef enum eMODE
|
||||
{
|
||||
//MODE_NONE = 0,
|
||||
MODE_ITEM = 1,
|
||||
MODE_NPC,
|
||||
NODE_SKILL
|
||||
} MODE;
|
||||
public:
|
||||
Dlg_FindInDB( MODE mode );
|
||||
~Dlg_FindInDB();
|
||||
|
||||
public:
|
||||
bool runDialog( HWND hWndParent );
|
||||
Dlg_FindInDB::MODE getMode() const { return this->m_mode; }
|
||||
|
||||
public: // results
|
||||
unsigned int itemID;
|
||||
char itemName[256];
|
||||
wchar_t itemNameW[256];
|
||||
|
||||
protected:
|
||||
MODE m_mode;
|
||||
};
|
||||
|
||||
#endif
|
||||
209
l2detect/GIArray.cpp
Normal file
209
l2detect/GIArray.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "GIArray.h"
|
||||
|
||||
GIArray *GIArray::s_instance = NULL;
|
||||
int GIArray::s_refCount = 0;
|
||||
|
||||
GIArray *GIArray::getInstance()
|
||||
{
|
||||
if( !GIArray::s_instance )
|
||||
{
|
||||
GIArray::s_instance = new GIArray();
|
||||
GIArray::s_refCount++;
|
||||
log_error( LOG_DEBUG, "GIArray: created instance\n" );
|
||||
}
|
||||
return GIArray::s_instance;
|
||||
}
|
||||
|
||||
void GIArray::freeInstance()
|
||||
{
|
||||
if( GIArray::s_instance )
|
||||
{
|
||||
GIArray::s_refCount--;
|
||||
if( GIArray::s_refCount == 0 )
|
||||
{
|
||||
delete GIArray::s_instance;
|
||||
GIArray::s_instance = NULL;
|
||||
log_error( LOG_DEBUG, "GIArray: freed instance\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GIArray::Init()
|
||||
{
|
||||
giArray_updateHWND = NULL;
|
||||
giArray_updateMSG = 0;
|
||||
giArray_count = 0;
|
||||
InitializeCriticalSection( &cs_gi_array );
|
||||
int i;
|
||||
for( i=0; i<GA_MAX_ITEMS; i++ ) gi_array[i] = new GroundItem();
|
||||
}
|
||||
|
||||
void GIArray::Free()
|
||||
{
|
||||
Lock();
|
||||
int i;
|
||||
for( i=0; i<GA_MAX_ITEMS; i++ )
|
||||
{
|
||||
if( gi_array[i] != NULL )
|
||||
{
|
||||
delete gi_array[i];
|
||||
gi_array[i] = NULL;
|
||||
}
|
||||
}
|
||||
giArray_count = 0;
|
||||
Unlock();
|
||||
DeleteCriticalSection( &cs_gi_array );
|
||||
}
|
||||
|
||||
int GIArray::AddGIInfo( GroundItem *pItemInfo )
|
||||
{
|
||||
Lock();
|
||||
// Add new npc info
|
||||
int idx = FindFreeIndex();
|
||||
if( idx == -1 )
|
||||
{
|
||||
Unlock();
|
||||
return -1;
|
||||
}
|
||||
if( !gi_array[idx] ) gi_array[idx] = new GroundItem();
|
||||
if( !gi_array[idx] )
|
||||
{
|
||||
Unlock();
|
||||
return -1;
|
||||
}
|
||||
memcpy( gi_array[idx], pItemInfo, sizeof(class GroundItem) );
|
||||
giArray_count++;
|
||||
Unlock();
|
||||
//log_error( LOG_OK, "GIArray: Added new[%d]: iid [%u] (%d,%d,%d)\n",
|
||||
// idx, gi_array[idx]->itemID, gi_array[idx]->x, gi_array[idx]->y, gi_array[idx]->z );
|
||||
return idx;
|
||||
}
|
||||
|
||||
void GIArray::UpdateGIInfo( int idx, GroundItem *pItemInfo )
|
||||
{
|
||||
Lock();
|
||||
// update info on existing
|
||||
if( !gi_array[idx] )
|
||||
{
|
||||
log_error( LOG_ERROR, "GIArray_UpdateGIInfo(): idx[%d] is free!\n", idx );
|
||||
// try to allocate!
|
||||
gi_array[idx] = new GroundItem();
|
||||
if( !gi_array[idx] )
|
||||
{
|
||||
Unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( gi_array[idx]->isUnused() ) log_error( LOG_ERROR, "GIArray_UpdateGIInfo(): idx[%d] is unused!\n", idx );
|
||||
memcpy( gi_array[idx], pItemInfo, sizeof(class GroundItem) );
|
||||
Unlock();
|
||||
//log_error( LOG_OK, "GIArray: Updated[%d]: iid [%u] (%d,%d,%d)\n",
|
||||
// idx, gi_array[idx]->itemID, gi_array[idx]->x, gi_array[idx]->y, gi_array[idx]->z );
|
||||
}
|
||||
|
||||
void GIArray::DelGIByArrayIdx( int idx )
|
||||
{
|
||||
if( idx<0 || (idx>=GA_MAX_ITEMS) ) return;
|
||||
Lock();
|
||||
if( gi_array[idx] )
|
||||
{
|
||||
//log_error( LOG_OK, "GIArray: deleted %u from index %d OK\n", gi_array[idx]->objectID, idx );
|
||||
gi_array[idx]->setUnused();
|
||||
giArray_count--;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void GIArray::DeleteAll()
|
||||
{
|
||||
Lock();
|
||||
int i;
|
||||
for( i=0; i<GA_MAX_ITEMS; i++ )
|
||||
{
|
||||
if( gi_array[i] ) gi_array[i]->setUnused();
|
||||
}
|
||||
giArray_count = 0;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void GIArray::Lock()
|
||||
{
|
||||
EnterCriticalSection( &cs_gi_array );
|
||||
}
|
||||
|
||||
void GIArray::Unlock()
|
||||
{
|
||||
LeaveCriticalSection( &cs_gi_array );
|
||||
}
|
||||
|
||||
int GIArray::FindGIByObjectID( unsigned int objectID )
|
||||
{
|
||||
int ret = -1;
|
||||
int i;
|
||||
Lock();
|
||||
for( i=0; i<GA_MAX_ITEMS; i++ )
|
||||
{
|
||||
if( gi_array[i] == NULL ) continue;
|
||||
if( gi_array[i]->objectID == objectID )
|
||||
{
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GIArray::FindFreeIndex()
|
||||
{
|
||||
int i;
|
||||
Lock();
|
||||
for( i=0; i<GA_MAX_ITEMS; i++ )
|
||||
{
|
||||
if( gi_array[i] == NULL )
|
||||
{
|
||||
gi_array[i] = new GroundItem(); // allocate new
|
||||
gi_array[i]->setUnused(); // and set as unused
|
||||
Unlock();
|
||||
return i;
|
||||
}
|
||||
if( gi_array[i]->isUnused() )
|
||||
{
|
||||
Unlock();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
log_error( LOG_ERROR, "GIArray_FindFreeIndex(): canot find free index, limit is %d!\n", GA_MAX_ITEMS );
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GIArray::DisplayToConsole()
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int nDisplayed = 0;
|
||||
log_error( LOG_USERAI, "=== Ground items: %d ===\n", giArray_count );
|
||||
if( giArray_count > 0 )
|
||||
{
|
||||
Lock();
|
||||
for( i=0; i<GA_MAX_ITEMS; i++ )
|
||||
{
|
||||
if( gi_array[i]->isUnused() )
|
||||
log_error( LOG_USERAI, "GI: %2d: <unused>\n", i );
|
||||
else
|
||||
{
|
||||
char itemName[256] = {0};
|
||||
L2Data_DB_GetItemNamePicByID( gi_array[i]->itemID, itemName, NULL );
|
||||
log_error( LOG_USERAI, "GI: %2d: itemID %u, objectID %u, count %d [%s]\n", i,
|
||||
gi_array[i]->itemID, gi_array[i]->objectID,
|
||||
gi_array[i]->count, itemName );
|
||||
nDisplayed++;
|
||||
}
|
||||
if( nDisplayed >= giArray_count ) break;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
log_error( LOG_USERAI, "=== Ground items End ===\n" );
|
||||
}
|
||||
43
l2detect/GIArray.h
Normal file
43
l2detect/GIArray.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef H_GI_ARRAY
|
||||
#define H_GI_ARRAY
|
||||
#include "GroundItem.h"
|
||||
|
||||
class GIArray
|
||||
{
|
||||
public:
|
||||
static GIArray *getInstance();
|
||||
static void freeInstance();
|
||||
protected:
|
||||
static GIArray *s_instance;
|
||||
static int s_refCount;
|
||||
protected:
|
||||
GIArray() { Init(); }
|
||||
~GIArray() { Free(); }
|
||||
public:
|
||||
static const int GA_MAX_ITEMS = 512;
|
||||
GroundItem *gi_array[GA_MAX_ITEMS];
|
||||
public:
|
||||
void Init();
|
||||
void Free();
|
||||
public:
|
||||
int AddGIInfo( GroundItem *pGIInfo );
|
||||
void UpdateGIInfo( int idx, GroundItem *pGIInfo );
|
||||
void DelGIByArrayIdx( int idx );
|
||||
void DeleteAll();
|
||||
public:
|
||||
void Lock();
|
||||
void Unlock();
|
||||
public:
|
||||
int FindGIByObjectID( unsigned int objectID );
|
||||
int FindFreeIndex();
|
||||
public:
|
||||
unsigned int getCount() const { return giArray_count; }
|
||||
void DisplayToConsole();
|
||||
protected:
|
||||
unsigned int giArray_count;
|
||||
CRITICAL_SECTION cs_gi_array;
|
||||
HWND giArray_updateHWND;
|
||||
UINT giArray_updateMSG;
|
||||
};
|
||||
|
||||
#endif
|
||||
209
l2detect/GameClient.cpp
Normal file
209
l2detect/GameClient.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
|
||||
extern class GameListener *g_pgame; // main.cpp
|
||||
extern class CConfig g_cfg; // main.cpp
|
||||
|
||||
GameClient::GameClient()
|
||||
{
|
||||
memset( key_client_sc, 0, sizeof(key_client_sc) );
|
||||
memset( key_client_cs, 0, sizeof(key_client_cs) );
|
||||
memset( key_server_sc, 0, sizeof(key_server_sc) );
|
||||
memset( key_server_cs, 0, sizeof(key_server_cs) );
|
||||
state = 0;
|
||||
gameProtoVer = 0;
|
||||
xor_enabled = false;
|
||||
logfile = NULL;
|
||||
logfileRaw = NULL;
|
||||
this->resetCounters( false );
|
||||
this->opcodeObfuscator = 0;
|
||||
sock_client = INVALID_SOCKET;
|
||||
sock_server = INVALID_SOCKET;
|
||||
clsObfuscator = 0;
|
||||
thisWasJustServerPing = false; // constructor
|
||||
hWndNotify = NULL;
|
||||
uMsgNotify = 0;
|
||||
InitializeCriticalSection( &cs_send );
|
||||
ai.clear();
|
||||
}
|
||||
|
||||
GameClient::~GameClient()
|
||||
{
|
||||
state = 0;
|
||||
gameProtoVer = 0;
|
||||
xor_enabled = false;
|
||||
if( logfile )
|
||||
{
|
||||
fflush( logfile );
|
||||
fclose( logfile );
|
||||
logfile = NULL;
|
||||
}
|
||||
this->resetCounters( false );
|
||||
this->opcodeObfuscator = 0;
|
||||
thisWasJustServerPing = false; // destructor
|
||||
if( sock_client != INVALID_SOCKET )
|
||||
{
|
||||
//closesocket( sock_client );
|
||||
L2PNet_closesocket( sock_client );
|
||||
sock_client = INVALID_SOCKET;
|
||||
}
|
||||
if( sock_server != INVALID_SOCKET )
|
||||
{
|
||||
//closesocket( sock_server );
|
||||
L2PNet_closesocket( sock_server );
|
||||
sock_server = INVALID_SOCKET;
|
||||
}
|
||||
// delete obfuscator, if exists
|
||||
if( this->clsObfuscator )
|
||||
{
|
||||
class L2PCodeObfuscator * lpco = (class L2PCodeObfuscator *)clsObfuscator;
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
ai.clear();
|
||||
hWndNotify = NULL;
|
||||
uMsgNotify = 0;
|
||||
}
|
||||
|
||||
void GameClient::logPacket(
|
||||
const unsigned char *bytes,
|
||||
unsigned int len,
|
||||
bool bFromServer )
|
||||
{
|
||||
if( !this->logfile || !bytes || (len<1) ) return;
|
||||
//
|
||||
//if( bFromServer ) return; //:)
|
||||
//
|
||||
if( bFromServer ) fprintf( logfile, "Server: " );
|
||||
else fprintf( logfile, "Client: " );
|
||||
if( len < 3 )
|
||||
{
|
||||
fprintf( logfile, "Warning: packet length = %u ( < 3!)\n", len );
|
||||
return;
|
||||
}
|
||||
char pname[256] = {0};
|
||||
L2_VERSION l2_version = (L2_VERSION)g_cfg.L2_version;
|
||||
if( !bFromServer ) l2_version = (L2_VERSION)g_cfg.L2_client_version;
|
||||
L2Packets_GetL2PacketName( l2_version, bFromServer, bytes[2], bytes[3], bytes[5], pname, 255 );
|
||||
fprintf( logfile, "Len %4u [%s] | %02X %02X / %02X / ", len, pname,
|
||||
bytes[0], bytes[1], bytes[2] );
|
||||
int i;
|
||||
for( i=3; i<(int)len; i++ )
|
||||
{
|
||||
fprintf( logfile, "%02X ", bytes[i] );
|
||||
if( ((i-2) % 4) == 0 ) fprintf( logfile, " " );
|
||||
}
|
||||
fprintf( logfile, "\n" );
|
||||
fflush( logfile );
|
||||
}
|
||||
|
||||
void GameClient::logPacketRaw(
|
||||
const unsigned char *bytes,
|
||||
unsigned int len,
|
||||
bool bFromServer )
|
||||
{
|
||||
if( !this->logfileRaw || !bytes || (len<1) ) return;
|
||||
//
|
||||
//if( bFromServer ) return; //:)
|
||||
//
|
||||
if( bFromServer ) fprintf( logfileRaw, "Server: " );
|
||||
else fprintf( logfileRaw, "Client: " );
|
||||
if( len < 3 )
|
||||
{
|
||||
fprintf( logfileRaw, "Warning: packet length = %u ( < 3!)\n", len );
|
||||
return;
|
||||
}
|
||||
fprintf( logfileRaw, "Len %4u | %02X %02X / %02X / ", len,
|
||||
bytes[0], bytes[1], bytes[2] );
|
||||
int i;
|
||||
for( i=3; i<(int)len; i++ )
|
||||
{
|
||||
fprintf( logfileRaw, "%02X ", bytes[i] );
|
||||
if( ((i-2) % 4) == 0 ) fprintf( logfileRaw, " " );
|
||||
}
|
||||
fprintf( logfileRaw, "\n" );
|
||||
fflush( logfileRaw );
|
||||
}
|
||||
|
||||
void GameClient::resetConnectedState()
|
||||
{
|
||||
// reset state
|
||||
state = 0;
|
||||
// reset other session vars: game proto ver, XOR encrypting
|
||||
gameProtoVer = 0;
|
||||
xor_enabled = false;
|
||||
// reset XOR encryting keys
|
||||
memset( key_client_sc, 0, sizeof(key_client_sc) );
|
||||
memset( key_client_cs, 0, sizeof(key_client_cs) );
|
||||
memset( key_server_sc, 0, sizeof(key_server_sc) );
|
||||
memset( key_server_cs, 0, sizeof(key_server_cs) );
|
||||
// sockets
|
||||
sock_client = INVALID_SOCKET;
|
||||
sock_server = INVALID_SOCKET;
|
||||
// obfuscator
|
||||
opcodeObfuscator = 0;
|
||||
if( this->clsObfuscator )
|
||||
{
|
||||
class L2PCodeObfuscator * lpco = (class L2PCodeObfuscator *)clsObfuscator;
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
log_error( LOG_DEBUG, "GameClient::resetConnectedState(): deleted obfuscator class\n" );
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
//thisWasJustServerPing = false; // NO!!! don't reset it here!
|
||||
//hWndNotify = NULL;
|
||||
//uMsgNotify = 0;
|
||||
}
|
||||
|
||||
void GameClient::resetCounters( bool addFakePacket )
|
||||
{
|
||||
counters.resetCounters();
|
||||
if( addFakePacket )
|
||||
{
|
||||
counters.addRcvdPacket( 10 );
|
||||
counters.addSentPacket( 10 );
|
||||
}
|
||||
}
|
||||
|
||||
void GameClient::getCounters( GameClientCounters& out ) const
|
||||
{
|
||||
out = counters;
|
||||
}
|
||||
|
||||
void GameClient::setCountersStartingExp( unsigned long long int exp )
|
||||
{
|
||||
if( counters.ullStartingExp == 0 )
|
||||
counters.ullStartingExp = exp;
|
||||
}
|
||||
|
||||
void GameClient::startCountersTimer()
|
||||
{
|
||||
counters.startTimer();
|
||||
}
|
||||
|
||||
void GameClient::setNotifyWindow( HWND notifyHwnd, UINT notifyMsg )
|
||||
{
|
||||
this->hWndNotify = notifyHwnd;
|
||||
this->uMsgNotify = notifyMsg;
|
||||
}
|
||||
|
||||
void GameClient::postNotify( WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if( hWndNotify == NULL || (uMsgNotify < WM_USER) ) return;
|
||||
PostMessage( hWndNotify, uMsgNotify, wParam, lParam );
|
||||
}
|
||||
|
||||
void GameClient::LockSend()
|
||||
{
|
||||
EnterCriticalSection( &cs_send );
|
||||
}
|
||||
|
||||
void GameClient::UnlockSend()
|
||||
{
|
||||
LeaveCriticalSection( &cs_send );
|
||||
}
|
||||
|
||||
132
l2detect/GameClient.h
Normal file
132
l2detect/GameClient.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef FAKELOGIN_GAMECLIENT_H_
|
||||
#define FAKELOGIN_GAMECLIENT_H_
|
||||
|
||||
#include "UserAI.h"
|
||||
#include "GameClientCounters.h"
|
||||
|
||||
// client state
|
||||
#define GCST_OFFLINE 0 // not connected to GS :)
|
||||
#define GCST_CONNECTED 1 // just connected to GS
|
||||
#define GCST_AUTHED 2 // passed GS auth, sees chars selection list
|
||||
#define GCST_IN_GAME 3 // selectedc har and entered game
|
||||
|
||||
// window notification wParam
|
||||
#define GCN_STATECHANGE 1 // lParam will hold new state
|
||||
|
||||
class GameClient
|
||||
{
|
||||
public:
|
||||
GameClient();
|
||||
virtual ~GameClient();
|
||||
|
||||
public: // sniffer functions
|
||||
bool PC_sniff( SOCKET scl, unsigned char *sip, unsigned short int sport );
|
||||
void PP_sniff_fromServer( unsigned char *bytes, unsigned int len );
|
||||
void PP_sniff_fromClient( unsigned char *bytes, unsigned int len );
|
||||
|
||||
public:
|
||||
// algorythm of processing with full packet modifying control
|
||||
bool PC_full( SOCKET scl, unsigned char *sip, unsigned short int sport );
|
||||
|
||||
// Parameters:
|
||||
//
|
||||
// returns true if packet was modified
|
||||
// if packet was not modified:
|
||||
// sets (*newLen) to len;
|
||||
// sets (*newBytes) to bytes
|
||||
// - caller should ignore newLen and newBytes content in this case
|
||||
// - caller should send original packet
|
||||
// if packet was modified:
|
||||
// sets (*newLen) to new length of packet
|
||||
// sets (*newBytes) to point to new bytes buffer
|
||||
// - newBytes are properly encoded if needed,
|
||||
// - caller just should send newBytes and free them after sending
|
||||
// if packet should be dropped:
|
||||
// sets (*newLen) to -1
|
||||
// - caller should ignore newLen and newBytes content
|
||||
// - caller should not send any packet :)
|
||||
//
|
||||
bool PP_full_fromServer( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen );
|
||||
|
||||
// Parameters:
|
||||
//
|
||||
// returns true if packet was modified
|
||||
// if packet was not modified:
|
||||
// sets (*newLen) to len;
|
||||
// sets (*newBytes) to bytes
|
||||
// - caller should ignore newLen and newBytes content in this case
|
||||
// - caller should send original packet
|
||||
// if packet was modified:
|
||||
// sets (*newLen) to new length of packet
|
||||
// sets (*newBytes) to point to new bytes buffer
|
||||
// - newBytes are properly encoded if needed,
|
||||
// - caller just should send newBytes and free them after sending
|
||||
// if packet should be dropped:
|
||||
// sets (*newLen) to -1
|
||||
// - caller should ignore newLen and newBytes content
|
||||
// - caller should not send any packet :)
|
||||
//
|
||||
bool PP_full_fromClient( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen );
|
||||
|
||||
// if packet was modified, it will be encoded again before resending
|
||||
bool PP_full_reencode_packet( unsigned char *bytes, unsigned int len, unsigned char *key );
|
||||
|
||||
public: // counters
|
||||
void resetCounters( bool addFakePacket );
|
||||
void getCounters( GameClientCounters& out ) const;
|
||||
void setCountersStartingExp( unsigned long long int exp );
|
||||
void startCountersTimer();
|
||||
public:
|
||||
int getState() const { return this->state; }
|
||||
bool InjectPacketToServer( unsigned char *bytes, unsigned int len, bool doObfuscate );
|
||||
bool InjectPacketToClient( unsigned char *bytes, unsigned int len );
|
||||
//void setHealItemsTable( HealItemsTable *other );
|
||||
void setNotifyWindow( HWND notifyHwnd, UINT notifyMsg );
|
||||
|
||||
protected:
|
||||
void LockSend();
|
||||
void UnlockSend();
|
||||
void logPacket( const unsigned char *bytes, unsigned int len, bool bFromServer );
|
||||
void logPacketRaw( const unsigned char *bytes, unsigned int len, bool bFromServer );
|
||||
void resetConnectedState();
|
||||
void postNotify( WPARAM wParam, LPARAM lParam );
|
||||
|
||||
public: // char state, inventory...
|
||||
UserAI ai;
|
||||
|
||||
bool wasJustServerPing() { return thisWasJustServerPing; }
|
||||
|
||||
protected:
|
||||
|
||||
// protocol state vars
|
||||
bool xor_enabled;
|
||||
unsigned char key_client_sc[32]; // key S->C (to re-encrypt FOR client side)
|
||||
unsigned char key_client_cs[32]; // key C->S (to decrypt FROM client side)
|
||||
unsigned char key_server_sc[32]; // key S->C (to decrypt FROM server side)
|
||||
unsigned char key_server_cs[32]; // key C->S (to re-encrypt FOR server side)
|
||||
unsigned int gameProtoVer;
|
||||
unsigned int opcodeObfuscator;
|
||||
void *clsObfuscator;
|
||||
bool thisWasJustServerPing; // remains true, when client just sends server ping
|
||||
|
||||
// system vars
|
||||
CRITICAL_SECTION cs_send;
|
||||
int state;
|
||||
FILE *logfile;
|
||||
FILE *logfileRaw;
|
||||
|
||||
// counters
|
||||
GameClientCounters counters;
|
||||
|
||||
// sockets
|
||||
SOCKET sock_client;
|
||||
SOCKET sock_server;
|
||||
|
||||
// notify window
|
||||
HWND hWndNotify;
|
||||
UINT uMsgNotify;
|
||||
};
|
||||
|
||||
#endif /*FAKELOGIN_GAMECLIENT_H_*/
|
||||
60
l2detect/GameClientCounters.cpp
Normal file
60
l2detect/GameClientCounters.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "stdafx.h"
|
||||
#include "GameClientCounters.h"
|
||||
|
||||
GameClientCounters::GameClientCounters()
|
||||
{
|
||||
resetCounters();
|
||||
}
|
||||
|
||||
GameClientCounters::GameClientCounters( const GameClientCounters& other )
|
||||
{
|
||||
this->operator=( other );
|
||||
}
|
||||
|
||||
GameClientCounters& GameClientCounters::operator=( const GameClientCounters& other )
|
||||
{
|
||||
this->ullBytesRcvd = other.ullBytesRcvd;
|
||||
this->ullBytesSent = other.ullBytesSent;
|
||||
this->ullPacketsRcvd = other.ullPacketsRcvd;
|
||||
this->ullPacketsSent = other.ullPacketsSent;
|
||||
this->startTime = other.startTime;
|
||||
this->ullStartingExp = other.ullStartingExp;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void GameClientCounters::resetCounters()
|
||||
{
|
||||
this->ullBytesRcvd = this->ullBytesSent =
|
||||
this->ullPacketsRcvd = this->ullPacketsSent = 0;
|
||||
this->startTime = 0;
|
||||
this->ullStartingExp = 0;
|
||||
}
|
||||
|
||||
void GameClientCounters::startTimer()
|
||||
{
|
||||
this->startTime = (unsigned)time( NULL );
|
||||
}
|
||||
|
||||
void GameClientCounters::addSentPacket( unsigned long long int packetLen )
|
||||
{
|
||||
this->ullPacketsSent++;
|
||||
this->ullBytesSent += packetLen;
|
||||
}
|
||||
|
||||
void GameClientCounters::addRcvdPacket( unsigned long long int packetLen )
|
||||
{
|
||||
this->ullPacketsRcvd++;
|
||||
this->ullBytesRcvd += packetLen;
|
||||
}
|
||||
|
||||
void GameClientCounters::calcNowStats( GameClient_NetStats *s )
|
||||
{
|
||||
unsigned int timeNow = (unsigned)time(NULL);
|
||||
s->timePassedSecs = ((double)(timeNow - startTime));
|
||||
s->avgSendSpeed = ((double)ullBytesSent) / (s->timePassedSecs);
|
||||
s->avgRecvSpeed = ((double)ullBytesRcvd) / (s->timePassedSecs);
|
||||
s->avgSendPacketsPerSec = ((double)ullPacketsSent) / (s->timePassedSecs);
|
||||
s->avgRecvPacketsPerSec = ((double)ullPacketsRcvd) / (s->timePassedSecs);
|
||||
s->avgRecvPacketSize = ((double)ullBytesRcvd) / ((double)ullPacketsRcvd);
|
||||
s->avgSendPacketSize = ((double)ullBytesSent) / ((double)ullPacketsSent);
|
||||
}
|
||||
39
l2detect/GameClientCounters.h
Normal file
39
l2detect/GameClientCounters.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef H_GAME_CLIENT_COUNTERS
|
||||
#define H_GAME_CLIENT_COUNTERS
|
||||
|
||||
class GameClient_NetStats
|
||||
{
|
||||
public:
|
||||
double timePassedSecs;
|
||||
double avgSendSpeed;
|
||||
double avgRecvSpeed;
|
||||
double avgSendPacketsPerSec;
|
||||
double avgRecvPacketsPerSec;
|
||||
double avgSendPacketSize;
|
||||
double avgRecvPacketSize;
|
||||
};
|
||||
|
||||
class GameClientCounters
|
||||
{
|
||||
public:
|
||||
GameClientCounters();
|
||||
GameClientCounters( const GameClientCounters& other );
|
||||
GameClientCounters& operator=( const GameClientCounters& other );
|
||||
public:
|
||||
void resetCounters();
|
||||
void startTimer();
|
||||
public:
|
||||
void addSentPacket( unsigned long long int packetLen );
|
||||
void addRcvdPacket( unsigned long long int packetLen );
|
||||
public:
|
||||
void calcNowStats( GameClient_NetStats *s );
|
||||
public:
|
||||
unsigned int startTime;
|
||||
unsigned long long int ullBytesSent;
|
||||
unsigned long long int ullBytesRcvd;
|
||||
unsigned long long int ullPacketsSent;
|
||||
unsigned long long int ullPacketsRcvd;
|
||||
unsigned long long int ullStartingExp;
|
||||
};
|
||||
|
||||
#endif
|
||||
341
l2detect/GameClient_full.cpp
Normal file
341
l2detect/GameClient_full.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "CharArray.h"
|
||||
#include "ClanList.h"
|
||||
#include "ProtocolConverter.h"
|
||||
//
|
||||
#include "RadarDllWnd.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
extern class GameListener *g_pgame;
|
||||
|
||||
bool GameClient::PC_full( SOCKET scl, unsigned char *sip, unsigned short int sport )
|
||||
{
|
||||
sock_client = INVALID_SOCKET;
|
||||
sock_server = INVALID_SOCKET;
|
||||
this->resetCounters( false );
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_full() started\n" );
|
||||
// assert
|
||||
if( (scl == INVALID_SOCKET) || (!sip) || (sport<1) )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::ProcessClient_full(): start assert failed\n" );
|
||||
return false;
|
||||
}
|
||||
// vars
|
||||
bool retVal = false;
|
||||
SOCKET sg = INVALID_SOCKET;
|
||||
char ssip[16] = {0};
|
||||
sprintf( ssip, "%d.%d.%d.%d", (int)sip[0], (int)sip[1], (int)sip[2], (int)sip[3] );
|
||||
|
||||
// first we should connect to real game server
|
||||
// create real GS socket
|
||||
sg = L2PNet_TCPsocket_create( true );
|
||||
if( sg == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::ProcessClient_full(): real GS socket create\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// connect to real game server
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_full(): Connecting to real game server %s:%d ", ssip, (int)sport );
|
||||
L2PNet_connect( sg, ssip, sport );
|
||||
int nTries = 20;
|
||||
int r = 0;
|
||||
while( nTries > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, "." );
|
||||
r = L2PNet_select( sg, L2PNET_SELECT_WRITE, 500, NULL, NULL );
|
||||
if( r == 1 ) break;
|
||||
nTries--;
|
||||
}
|
||||
|
||||
if( r == 1 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, " Connected. Tries left: %d\n", nTries );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error_np( LOG_DEBUG, " Failed!\n", nTries );
|
||||
log_error( LOG_ERROR, "PC_full(): cannot connect to real game server!\n" );
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
log_error_np( LOG_DEBUG, " Not connected.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate receive buffer
|
||||
unsigned char *packbuffer = (unsigned char *)malloc( 65536 ); // 64 Kb :)
|
||||
if( !packbuffer )
|
||||
{
|
||||
log_error( LOG_ERROR, "PC_full(): cannot allocate 64 Kb packet receive buffer!\n" );
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
log_error_np( LOG_DEBUG, " Not connected.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// open log file
|
||||
if( g_cfg.LogGamePackets )
|
||||
{
|
||||
char filename[256];
|
||||
time_t nowTime;
|
||||
time( &nowTime );
|
||||
sprintf( filename, "%s%u.txt", g_cfg.LogGameFileNamePrefix, (unsigned int)nowTime );
|
||||
this->logfile = fopen( filename, "wt" );
|
||||
if( !logfile )
|
||||
log_error( LOG_WARNING, "GameClient::PC_full(): Cannot open log file [%s] for writing!\n",
|
||||
filename );
|
||||
}
|
||||
|
||||
// set initial game client state
|
||||
this->state = GCST_CONNECTED;
|
||||
this->thisWasJustServerPing = false; // initial assign before any packet recieved
|
||||
bool bWasModified = false;
|
||||
this->sock_client = scl;
|
||||
this->sock_server = sg;
|
||||
|
||||
ProtoConv_Init();
|
||||
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
ai.notifyEvent( UAI_EVENT_START );
|
||||
this->counters.startTimer();
|
||||
|
||||
// infinite loop
|
||||
int recvTimeout = 120; // seconds
|
||||
long recvTimeoutMsec = recvTimeout * 1000;
|
||||
int selectTimeout = 1; // seconds
|
||||
struct timeval tv;
|
||||
fd_set fdReadSet;
|
||||
unsigned char *newBytes = NULL;
|
||||
unsigned int rcvdLen = 0;
|
||||
unsigned int sentLen = 0;
|
||||
unsigned int newLen = 0;
|
||||
int wsaerr = 0;
|
||||
unsigned int scode = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
scode = g_pgame->getLastSignal();
|
||||
if( scode == FLGS_STOP )
|
||||
{
|
||||
log_error( LOG_DEBUG, "GameClient::PC_full(): exit signal\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
tv.tv_sec = selectTimeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// check readability on sockets
|
||||
FD_ZERO( &fdReadSet ); // zero set
|
||||
FD_SET( scl, &fdReadSet ); // add client socket to read set
|
||||
FD_SET( sg, &fdReadSet ); // add real GS socket to read set
|
||||
//
|
||||
r = L2PNet_select_wrapper_DUMB( 0, &fdReadSet, 0, 0, &tv );
|
||||
if( r == 0 ) /* timeout failed */
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "." );
|
||||
}
|
||||
else if( r == -1 ) /* select error */
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "\nselect() ERROR\n" );
|
||||
// TODO: what to do on select() error?
|
||||
wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock select() error %d: ", wsaerr );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
//log_error( LOG_ERROR, "ProcessClient_full(): socket select() ERROR!\n" );
|
||||
//log_error( LOG_ERROR, "ProcessClient_full(): closing processing\n" );
|
||||
//goto netError;
|
||||
}
|
||||
else if( r > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "\nselect(): number of sockets ready: %d\n", r );
|
||||
// client sent something?
|
||||
if( L2PNet_FD_ISSET( scl, &fdReadSet ) )
|
||||
{
|
||||
//log_error( LOG_DEBUGDUMP, "C->S (reading...)\n" );
|
||||
// receive packet from client
|
||||
r = L2PacketReceive_buffer( scl, recvTimeoutMsec, &rcvdLen, packbuffer );
|
||||
//log_error( LOG_DEBUGDUMP, "Received %u bytes from client\n", rcvdLen );
|
||||
if( (r == 0) && (rcvdLen == 0) )
|
||||
{
|
||||
log_error( LOG_WARNING, "Connection closed by client?\n" );
|
||||
goto closeSocks;
|
||||
}
|
||||
if( r <= 0 )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2PacketReceive() failed!\n" );
|
||||
wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock error %d: ", wsaerr );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_ERROR, "\n" );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// process it! :)
|
||||
bWasModified = PP_full_fromClient( packbuffer, rcvdLen, &newBytes, &newLen );
|
||||
if( newLen != -1 ) // -1 means - Drop packet
|
||||
{
|
||||
// resend packet to server after processing
|
||||
LockSend();
|
||||
r = L2PacketSend2( newBytes, sg, recvTimeoutMsec, &sentLen );
|
||||
UnlockSend();
|
||||
// if packet was not modified: newBytes points to the same memory as p points
|
||||
// if packet was modified: newBytes points to new memory
|
||||
// ... in this case we should free new memory separately
|
||||
if( newBytes != packbuffer ) free( newBytes ); // :)
|
||||
// in both cases newLen contains length to be sent
|
||||
|
||||
//log_error( LOG_DEBUGDUMP, "Sent %u bytes to server\n", sentLen );
|
||||
if( sentLen != newLen ) // we must send newLen
|
||||
{
|
||||
log_error( LOG_ERROR, "PC_full(): After L2PacketSend2() C->S sentLen != newLen!!! (%u != %u, bWasModified = %d)\n",
|
||||
sentLen, newLen, (int)bWasModified );
|
||||
goto netError;
|
||||
}
|
||||
// counters
|
||||
this->counters.addSentPacket( sentLen );
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// log_error( LOG_DEBUGDUMP, "PC_full(): dropped packet...\n" );
|
||||
//}
|
||||
}
|
||||
|
||||
// server sent something?
|
||||
if( L2PNet_FD_ISSET( sg, &fdReadSet ) )
|
||||
{
|
||||
//log_error( LOG_DEBUGDUMP, "S->C (reading...)\n" );
|
||||
// receive packet from server
|
||||
r = L2PacketReceive_buffer( sg, recvTimeoutMsec, &rcvdLen, packbuffer );
|
||||
//log_error( LOG_DEBUGDUMP, "Received %u bytes from server\n", rcvdLen );
|
||||
if( (r == 0) && (rcvdLen == 0) )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Connection closed by server?\n" );
|
||||
goto closeSocks;
|
||||
}
|
||||
if( r <= 0 )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2PacketReceive() failed!\n" );
|
||||
wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock error %d: ", wsaerr );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_ERROR, "\n" );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// counters
|
||||
this->counters.addRcvdPacket( rcvdLen );
|
||||
|
||||
// process it! :)
|
||||
bWasModified = PP_full_fromServer( packbuffer, rcvdLen, &newBytes, &newLen );
|
||||
if( newLen != -1 ) // -1 means - Drop packet
|
||||
{
|
||||
// resend packet to client
|
||||
LockSend();
|
||||
r = L2PacketSend2( newBytes, scl, recvTimeoutMsec, &sentLen );
|
||||
UnlockSend();
|
||||
// if packet was not modified: newBytes points to the same memory as p points
|
||||
// if packet was modified: newBytes points to new memory
|
||||
// ... in this case we should free new memory separately
|
||||
if( newBytes != packbuffer )
|
||||
{
|
||||
//log_error( LOG_OK, "Packet was modified, freeing newBytes buffer (newLen = %u)\n", newLen );
|
||||
free( newBytes ); // :)
|
||||
}
|
||||
// in both cases newLen contains length to be sent
|
||||
|
||||
//log_error( LOG_DEBUGDUMP, "Sent %u bytes to client\n", sentLen );
|
||||
if( sentLen != newLen )
|
||||
{
|
||||
log_error( LOG_ERROR, "PC_full(): After L2PacketrSend2() S->C sent != rcvd!!! (%u != %u, bWasModified = %d)\n",
|
||||
sentLen, newLen, (int)bWasModified );
|
||||
goto netError;
|
||||
}
|
||||
} // newLen != -1
|
||||
}
|
||||
} // (r>0) // select() OK
|
||||
}// while(1)
|
||||
|
||||
retVal = true;
|
||||
netError:
|
||||
retVal = true;
|
||||
if( wsaerr > 0 )
|
||||
{
|
||||
retVal = false;
|
||||
log_error( LOG_ERROR, "PC_full(): some error happened or network connection closed...\n" );
|
||||
}
|
||||
closeSocks:
|
||||
// save radar window size
|
||||
PostMessage( g_radardll_hwnd, WMMY_SAVE_WINDOW_SIZE, 0, 0 );
|
||||
// logfile
|
||||
if( this->logfile )
|
||||
{
|
||||
fclose( this->logfile );
|
||||
this->logfile = NULL;
|
||||
}
|
||||
// free packbuffer
|
||||
if( packbuffer ) free( packbuffer );
|
||||
packbuffer = NULL;
|
||||
// stop AI thread
|
||||
ai.notifyEvent( UAI_EVENT_STOP );
|
||||
// reset internal state
|
||||
this->resetConnectedState();
|
||||
// sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
// lists
|
||||
CharArray_DeleteAll();
|
||||
ClanList_DeleteAll();
|
||||
// switch state
|
||||
this->state = GCST_OFFLINE;
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
// log counters
|
||||
GameClient_NetStats netstats;
|
||||
counters.calcNowStats( &netstats );
|
||||
log_error_np( LOG_OK, "=============================================\n" );
|
||||
log_error_np( LOG_OK, "Network usage stats:\n" );
|
||||
log_error_np( LOG_OK, "Bytes, packets sent: %I64u, %I64u\n", counters.ullBytesSent, counters.ullPacketsSent );
|
||||
log_error_np( LOG_OK, "Bytes, packets rcvd: %I64u, %I64u\n", counters.ullBytesRcvd, counters.ullPacketsRcvd );
|
||||
log_error_np( LOG_OK, "Time connected: %0.2f seconds\n", netstats.timePassedSecs );
|
||||
log_error_np( LOG_OK, "Avg send speed: %0.2f bytes/sec\n", netstats.avgSendSpeed );
|
||||
log_error_np( LOG_OK, "Avg recv speed: %0.2f bytes/sec\n", netstats.avgRecvSpeed );
|
||||
log_error_np( LOG_OK, "Avg send L2 packets: %0.2f packets/sec\n", netstats.avgSendPacketsPerSec );
|
||||
log_error_np( LOG_OK, "Avg recv L2 packets: %0.2f packets/sec\n", netstats.avgRecvPacketsPerSec );
|
||||
log_error_np( LOG_OK, "Avg out packet size: %0.2f bytes\n", netstats.avgSendPacketSize );
|
||||
log_error_np( LOG_OK, "Avg in packet size: %0.2f bytes\n", netstats.avgRecvPacketSize );
|
||||
log_error_np( LOG_OK, "=============================================\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
|
||||
//
|
||||
log_error( LOG_DEBUG, "GameClient::PC_full() ending, returning %d\n", (int)retVal );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
// if packet was modified, it will be encoded again before resending
|
||||
bool GameClient::PP_full_reencode_packet( unsigned char *bytes, unsigned int len, unsigned char *key )
|
||||
{
|
||||
if( !this->xor_enabled ) return true; // no need to encrypt now - XOR keys not received yet
|
||||
//if( !bytes || (len<3) || !key ) return false; // asserts
|
||||
//L2GamePacket p;
|
||||
//if( !p.setBytes( bytes, len ) ) return false;
|
||||
//if( !p.encodeXOR( key ) ) return false;
|
||||
//memcpy( bytes, p.getBytesPtr(), len );
|
||||
// speed optimisation - remove constructor(), setBytes() calls and memcpy() call
|
||||
bool ret = L2GamePacket::encodeXOR_buffer( bytes, len, key ); // encode directly in buffer
|
||||
/*log_error( LOG_DEBUGDUMP, "PP_full_reencode_packet(): packet of len %u re-encode result: %d\n",
|
||||
len, (int)ret );*/
|
||||
return ret;
|
||||
}
|
||||
581
l2detect/GameClient_full_PP_client.cpp
Normal file
581
l2detect/GameClient_full_PP_client.cpp
Normal file
@@ -0,0 +1,581 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "L2PacketTypes.h"
|
||||
#include "accountBind.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
// Parameters:
|
||||
//
|
||||
// returns true if packet was modified
|
||||
// if packet was not modified:
|
||||
// sets (*newLen) to len;
|
||||
// sets (*newBytes) to bytes
|
||||
// - caller can ignore newLen and newBytes content in this case
|
||||
// - caller can use newLen and newBytes instead of original values (they are the same)
|
||||
// - caller should send original packet
|
||||
// - caller should free original packet buffer
|
||||
// if packet was modified:
|
||||
// sets (*newLen) to new length of packet
|
||||
// sets (*newBytes) to point to new bytes buffer
|
||||
// - newBytes are properly encoded if needed,
|
||||
// - caller just should send newBytes and free them after sending
|
||||
// - caller should also free original packet buffer
|
||||
// if packet should be dropped:
|
||||
// sets (*newLen) to -1
|
||||
// - caller should ignore newLen and newBytes content
|
||||
// - caller should not send any packet :)
|
||||
// - caller should free original packet buffer
|
||||
//
|
||||
bool GameClient::PP_full_fromClient( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
// assume packet was not modified
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
//
|
||||
//int i = 0;
|
||||
bool bPacketWasModified = false; // initially packet is not modified
|
||||
if( !bytes || len<1 ) return bPacketWasModified;
|
||||
if( len<3 )
|
||||
{
|
||||
log_error( LOG_WARNING, "PP_full_fromClient(): packet len < 3!\n" );
|
||||
return bPacketWasModified;
|
||||
}
|
||||
|
||||
// should we decrypt it?
|
||||
if( this->xor_enabled ) L2GamePacket::decodeXOR_buffer( bytes, len, this->key_client_cs );
|
||||
|
||||
// parse it
|
||||
unsigned char ptype = bytes[2];
|
||||
unsigned short int ptype2 = 0x0000;
|
||||
unsigned short int ptype3 = 0x0000;
|
||||
if( len >= 5 )
|
||||
{
|
||||
ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
}
|
||||
if( len >= 7 )
|
||||
{
|
||||
ptype3 |= (unsigned short int)(bytes[5] & 0xFFFF);
|
||||
ptype3 |= (unsigned short int)(bytes[6] << 8 & 0xFFFF);
|
||||
}
|
||||
|
||||
// obfuscator
|
||||
class L2PCodeObfuscator *lpco;
|
||||
lpco = (class L2PCodeObfuscator *)this->clsObfuscator;
|
||||
|
||||
if( lpco )
|
||||
{
|
||||
if( lpco->isEnabled() )
|
||||
{
|
||||
unsigned char pcode_prev = ptype;
|
||||
unsigned short pcode2_prev = ptype2;
|
||||
bool decode_res = false;
|
||||
try
|
||||
{
|
||||
decode_res = lpco->decodeOpcode( ptype, ptype2 );
|
||||
}
|
||||
catch( L2P_DeObfuscateException& e )
|
||||
{
|
||||
log_error( LOG_ERROR, "PP_full_fromClient(): L2P_DeObfuscateException: %s\n", e.what() );
|
||||
}
|
||||
if( decode_res )
|
||||
{
|
||||
if( pcode2_prev == ptype2 ) // 2nd opcode not changed, not double-opcode packet
|
||||
log_error( LOG_DEBUG, " **** de-obfuscated %02X -> %02X ****\n", pcode_prev, ptype );
|
||||
else
|
||||
log_error( LOG_DEBUG, " **** de-obfuscated %02X:%02X -> %02X:%02X ****\n",
|
||||
pcode_prev, pcode2_prev, ptype, ptype2 );
|
||||
}
|
||||
else
|
||||
log_error( LOG_ERROR, "PP_full_fromClient(): ERROR de-obfuscating %02X\n", pcode_prev );
|
||||
}
|
||||
}
|
||||
|
||||
// log packet here, when it is decrypted, and opcode is deobfuscated, if log game packets is enabled
|
||||
if( this->logfile )
|
||||
{
|
||||
unsigned char prev_1 = bytes[2];
|
||||
unsigned short prev_2 = bytes[3] | (bytes[4] << 8);
|
||||
unsigned short prev_3 = bytes[5] | (bytes[6] << 8);
|
||||
if( this->clsObfuscator )
|
||||
{
|
||||
// replace opcode byte in bytes array to de-obfuscated opcode
|
||||
// to make log readable
|
||||
bytes[2] = ptype;
|
||||
if( len >= 5 )
|
||||
{
|
||||
bytes[3] = ptype2 & 0xFF;
|
||||
bytes[4] = (ptype2 >> 8) & 0xFF;
|
||||
if( len >= 7 )
|
||||
{
|
||||
bytes[5] = ptype3 & 0xFF;
|
||||
bytes[6] = (ptype3 >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
logPacket( bytes, len, false ); // false - from client
|
||||
if( this->clsObfuscator )
|
||||
{
|
||||
// restore opcode byte in bytes array to original
|
||||
// to keep packet 'as is'
|
||||
bytes[2] = prev_1;
|
||||
if( len >= 5 )
|
||||
{
|
||||
bytes[3] = prev_2 & 0xFF;
|
||||
bytes[4] = (prev_2 >> 8) & 0xFF;
|
||||
if( len >= 7 )
|
||||
{
|
||||
bytes[5] = prev_3 & 0xFF;
|
||||
bytes[6] = (prev_3 >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
L2PacketTypes_LogClient( (L2_VERSION)g_cfg.L2_client_version, this->state, ptype, ptype2, ptype3 );
|
||||
|
||||
// special handling packet sequential number
|
||||
if( this->counters.ullPacketsSent == 0 )
|
||||
{
|
||||
// client sends first packet - ProtocolVersion
|
||||
if( g_cfg.OverrideGameProtocolVersion > 0 )
|
||||
{
|
||||
// we can replace ProtocolVersion now...
|
||||
int cur_pv = bytes[3] | (bytes[4]<<8) | (bytes[5]<<16) | (bytes[6]<<24);
|
||||
// check for client pings server (usually: pv == -2 or 0xFFFFFFFE)
|
||||
if( (cur_pv >= 0xFFFFFFF0) || (cur_pv < 0) )
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Received client ping server... no process\n" );
|
||||
this->thisWasJustServerPing = true; // received client ping (full)
|
||||
return false; // flag: packet was not modified, and no need to re-encode it
|
||||
}
|
||||
//
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion from %d to %d\n",
|
||||
cur_pv, g_cfg.OverrideGameProtocolVersion );
|
||||
bytes[3] = (unsigned char)( (g_cfg.OverrideGameProtocolVersion & 0x000000FF) );
|
||||
bytes[4] = (unsigned char)( (g_cfg.OverrideGameProtocolVersion & 0x0000FF00) >> 8 );
|
||||
if( g_cfg.OverrideGameProtocolVersion == 828 )
|
||||
{
|
||||
/* Overriding to Kamael T1. we must replace also last 4 bytes */
|
||||
bytes[263] = 0x8D;
|
||||
bytes[264] = 0x71;
|
||||
bytes[265] = 0x5F;
|
||||
bytes[266] = 0x08;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion to T1: Kamael\n" );
|
||||
}
|
||||
if( g_cfg.OverrideGameProtocolVersion == 831 )
|
||||
{
|
||||
/* Overriding to Hellbound T1.5. we must replace also last 4 bytes */
|
||||
bytes[263] = 0xFB;
|
||||
bytes[264] = 0x87;
|
||||
bytes[265] = 0xB9;
|
||||
bytes[266] = 0x4A;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion to T1.5: Hellbound\n" );
|
||||
}
|
||||
if( g_cfg.OverrideGameProtocolVersion == 851 )
|
||||
{
|
||||
/* Overriding to Gracia T2. we must replace also last 4 bytes */
|
||||
bytes[263] = 0xDF;
|
||||
bytes[264] = 0xB8;
|
||||
bytes[265] = 0x3B;
|
||||
bytes[266] = 0x54;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion to T2: Gracia Part 1\n" );
|
||||
}
|
||||
if( g_cfg.OverrideGameProtocolVersion >= 12 && g_cfg.OverrideGameProtocolVersion <= 17 )
|
||||
{
|
||||
/* Overriding to Gracia T2.2. we must replace also last 4 bytes */
|
||||
bytes[263] = 0xEB;
|
||||
bytes[264] = 0xEF;
|
||||
bytes[265] = 0x3D;
|
||||
bytes[266] = 0xE6;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion to T2.2: Gracia Part 2\n" );
|
||||
}
|
||||
if( g_cfg.OverrideGameProtocolVersion >= 83 && g_cfg.OverrideGameProtocolVersion <= 87 )
|
||||
{
|
||||
/* Overriding to Gracia T2.3. we must replace also last 4 bytes */
|
||||
bytes[263] = 0x11;
|
||||
bytes[264] = 0x5D;
|
||||
bytes[265] = 0x1F;
|
||||
bytes[266] = 0x60;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion to T2.3: Gracia Final\n" );
|
||||
}
|
||||
if( g_cfg.OverrideGameProtocolVersion >= 146 && g_cfg.OverrideGameProtocolVersion <= 148 )
|
||||
{
|
||||
/* Overriding to Gracia T2.4. we must replace also last 4 bytes */
|
||||
bytes[263] = 0xA6;
|
||||
bytes[264] = 0x23;
|
||||
bytes[265] = 0xF4;
|
||||
bytes[266] = 0xFE;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion: Overriding ProtocolVersion to T2.4: Gracia Epilogue\n" );
|
||||
}
|
||||
return true; // flag that packet was modified :)
|
||||
// we can use return here, because encoding is not required for this packet
|
||||
// packet will be sent to server as is, without encoding
|
||||
}
|
||||
}
|
||||
// special handling packet sequential number end
|
||||
|
||||
switch( this->state )
|
||||
{
|
||||
case GCST_CONNECTED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // ProtocolVersion // Interlude
|
||||
case 0x0e: // ProtocolVersion // Hellbound
|
||||
{
|
||||
L2Game_ProtocolVersion *p = new L2Game_ProtocolVersion( bytes, len );
|
||||
p->read_protoVer( &(this->gameProtoVer) );
|
||||
delete p;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion %u\n", this->gameProtoVer );
|
||||
if( this->gameProtoVer >= 0xFFFFFFF0 )
|
||||
{
|
||||
this->thisWasJustServerPing = true; // received client ping (full)
|
||||
log_error( LOG_PACKETNAME, "Received client ping server... no process\n" );
|
||||
}
|
||||
} break; // ProtocolVersion
|
||||
// case 0x08: // AuthLogin // Interlude
|
||||
case 0x2b: // AuthLogin // Hellbound
|
||||
{
|
||||
L2Game_AuthLogin *p = new L2Game_AuthLogin( bytes, len );
|
||||
char login[32] = {0};
|
||||
p->read_login( login );
|
||||
delete p;
|
||||
log_error( LOG_DEBUG, "Client: 2b AuthLogin: Login: \"%s\"\n", login );
|
||||
#ifdef _ACCOUNT_BIND
|
||||
if( !isValidAccount( login ) )
|
||||
{
|
||||
log_error( LOG_ERROR, "Client: invalid account name (not bound to this). Exiting.\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
L2PNet_shutdown( this->sock_client );
|
||||
L2PNet_shutdown( this->sock_server );
|
||||
Sleep( 2000 );
|
||||
L2PNet_closesocket( this->sock_client );
|
||||
L2PNet_closesocket( this->sock_server );
|
||||
ExitProcess( 123 );
|
||||
}
|
||||
#endif
|
||||
} break; // AuthLogin
|
||||
//default:
|
||||
// {
|
||||
// log_error( LOG_DEBUGDUMP, "Client: Unknown packet %02X in state: CONNECTED\n",
|
||||
// (unsigned int)ptype );
|
||||
// if( g_cfg.DumpUnknownToStdout )
|
||||
// {
|
||||
// printf( "============================================\n" );
|
||||
// L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
// p->dumpToFile( stdout );
|
||||
// delete p;
|
||||
// printf( "============================================\n" );
|
||||
// }
|
||||
// } break;
|
||||
} // switch( ptype )
|
||||
} break; // CONNECTED
|
||||
|
||||
|
||||
//case GCST_AUTHED:
|
||||
//{
|
||||
// switch( ptype )
|
||||
// {
|
||||
//case 0x00: // LogoutRequest
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 00 LogoutRequest\n" );
|
||||
// } break;
|
||||
//case 0x12: // CharacterSelect // Hellbound
|
||||
// {
|
||||
// int charSlot = bytes[3];
|
||||
// //L2Game_CharacterSelect *p = new L2Game_CharacterSelect( bytes, len );
|
||||
// log_error( LOG_PACKETNAME, "Client: 12 CharacterSelect: #%d\n", charSlot );
|
||||
// //this->state = GCST_IN_GAME;
|
||||
// //log_error( LOG_DEBUG, "Client: 12 CharacterSelect: switch state to IN_GAME\n" );
|
||||
// } break; // CharacterSelect
|
||||
//case 0x13: // NewCharacter
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 13 NewCharacter\n" );
|
||||
// } break; // NewCharacter
|
||||
//case 0x0c: // CharacterCreate
|
||||
// {
|
||||
// wchar_t charNameU[64] = {0};
|
||||
// char charName[64] = {0};
|
||||
// wcscpy( charNameU, (const wchar_t *)(bytes+3) );
|
||||
// sprintf( charName, "%S", charNameU );
|
||||
// log_error( LOG_PACKETNAME, "Client: 0c CharacterCreate [%s]\n", charName );
|
||||
// } break; // CharacterCreate
|
||||
//case 0xd0:
|
||||
// {
|
||||
// ptype2 = 0x0000;
|
||||
// if( len >= 5 )
|
||||
// {
|
||||
// ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
// ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
// if( ptype2 == 0x0039 )
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: D0:39 RequestGotoLobby\n" );
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log_error( LOG_WARNING, "Client: Unknown opcode2 %04X for state AUTHED packet 0xD0\n",
|
||||
// (unsigned int)ptype2 );
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// log_error( LOG_WARNING, "Client: (AUTHED) sent 0xd0 without second opcode!\n" );
|
||||
// } break; // double opcode packet
|
||||
//default:
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: Unknown packet %02X in state: AUTHED\n",
|
||||
// (unsigned int)ptype );
|
||||
// if( g_cfg.DumpUnknownToStdout )
|
||||
// {
|
||||
// printf( "============================================\n" );
|
||||
// L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
// p->dumpToFile( stdout );
|
||||
// delete p;
|
||||
// printf( "============================================\n" );
|
||||
// }
|
||||
// } break;
|
||||
//} // switch( ptype )
|
||||
//} break; // AUTHED
|
||||
|
||||
|
||||
case GCST_IN_GAME:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // LogoutRequest
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 00 LogoutRequest\n" );
|
||||
// } break;
|
||||
case 0x0f: // MoveBackwardToLocation
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Client: 0f MoveBackwardToLocation\n" );
|
||||
if( g_cfg.L2Walker_FixMoveBackwardToLocation )
|
||||
{
|
||||
//log_error( LOG_OK, "Fixing L2Walker's MoveBackwardToLocation\n" );
|
||||
if( len == 27 )
|
||||
{
|
||||
//log_error( LOG_OK, "It is L2Walker's packet\n" );
|
||||
unsigned char *np = (unsigned char *)malloc( len + 4 );
|
||||
if( np )
|
||||
{
|
||||
(*newBytes) = np;
|
||||
(*newLen) = len + 4;
|
||||
memcpy( np, bytes, len );
|
||||
np[0] = ((unsigned char)31); // length of correct packet must be 31
|
||||
np[1] = 0;
|
||||
np[len + 0] = 0x01;
|
||||
np[len + 1] = 0x00;
|
||||
np[len + 2] = 0x00;
|
||||
np[len + 3] = 0x00;
|
||||
//
|
||||
bPacketWasModified = true; // so it will be encoded in the end of this function
|
||||
}
|
||||
//else log_error( LOG_ERROR, "malloc() error!\n" );
|
||||
}
|
||||
//else if( len == 31 )
|
||||
//{
|
||||
// log_error( LOG_OK, "It is normal client's packet. No need to change\n" );
|
||||
//}
|
||||
//else log_error( LOG_ERROR, "Unknown MoveBackwardToLocation packet!\n" );
|
||||
}
|
||||
} break;
|
||||
//case 0x11: // EnterWorld
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 11 EnterWorld\n" );
|
||||
// } break;
|
||||
//case 0x14: // RequestItemList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 14 RequestItemList\n" );
|
||||
// } break;
|
||||
//case 0x19: // UseItem
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 19 UseItem\n" );
|
||||
// } break;
|
||||
case 0x1F: // Action
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Client: 1F Action\n" );
|
||||
L2Game_Action *p = new L2Game_Action( bytes, len );
|
||||
unsigned int actionObjectId = p->read_objectID();
|
||||
p->read_originX();
|
||||
p->read_originY();
|
||||
p->read_originZ();
|
||||
//char useShift = p->read_useShift();
|
||||
delete p;
|
||||
// notify LockTarget manager
|
||||
ai.lockTargetMgr.onUserRequestAction( actionObjectId );
|
||||
//
|
||||
//if( useShift /* && g_cfg.altGameViewNpc */ )
|
||||
//{
|
||||
// L2OBJECT_TYPE objType = L2OT_NONE;
|
||||
// int index = -1;
|
||||
// if( WorldObjectTree_GetInfoByObjectID( oid, &objType, &index ) )
|
||||
// {
|
||||
// // disable Shift + click on NPC
|
||||
// /*if( objType == L2OT_NPC )
|
||||
// {
|
||||
// L2Npc *npc = npc_array[index];
|
||||
// char filename[256];
|
||||
// sprintf( filename, "npc_%d_stats.txt", npc->templateID );
|
||||
// FILE *f = fopen( filename, "wt" );
|
||||
// fprintf( f, "x,y,z,heading: (%d,%d,%d) %u\n", npc->x, npc->y, npc->z, npc->heading );
|
||||
// fprintf( f, "mAtkSpd, pAtkSpd: %d, %d\n", npc->mAtkSpd, npc->pAtkSpd );
|
||||
// fprintf( f, "runSpeed, walkSpeed: %d, %d\n", npc->runSpeed, npc->walkSpeed );
|
||||
// fprintf( f, "colR, colH: %0.2f, %0.2f\n", npc->collisionRadius, npc->collisionHeight );
|
||||
// fprintf( f, "rhand, chest, lhand: %u, %u, %u\n", npc->iid_right_hand, npc->iid_chest, npc->iid_left_hand );
|
||||
// fclose( f );
|
||||
// }*/
|
||||
// // maybe add Shift + click on player action? :)
|
||||
// }
|
||||
//}
|
||||
} break;
|
||||
case 0x22: // RequestLinkHtml
|
||||
{
|
||||
// this packet requires handling... it may be dropped if AI decides to
|
||||
this->ai.UAI_process_RequestBypassToServer( bytes, len, newBytes, newLen );
|
||||
} break;
|
||||
case 0x23: // RequestBypassToServer
|
||||
{
|
||||
// this packet requires handling... it may be dropped if AI decides to
|
||||
this->ai.UAI_process_RequestBypassToServer( bytes, len, newBytes, newLen );
|
||||
} break;
|
||||
case 0x36: // ChangeWaitType2
|
||||
{
|
||||
if( g_cfg.L2Walker_FixChangeWaitType2 )
|
||||
{
|
||||
log_error( LOG_OK, "Client: Fixing 36 ChangeWaitType2\n" );
|
||||
// ChangeWaitType2 format:
|
||||
// * Client: Len 7 | 07 00 / 36 / 00 00 00 00 - sit
|
||||
// * Client: Len 7 | 07 00 / 36 / 01 00 00 00 - stand
|
||||
// Instead of ChangeWaitType2 send RequestActionUse, so does client!
|
||||
// only L2Walker sends ChangeWaitType2 :\
|
||||
// RequestActionUse sit/stand format:
|
||||
// * Client: Len 12 | 0C 00 / 56 / 00 00 00 00 00 00 00 00 00
|
||||
// TODO: opcode obfuscate
|
||||
unsigned char opcode_RequestActionUse = 0x56; // RequestActionUse
|
||||
unsigned short doubleOpcode = 0x00;
|
||||
if( this->clsObfuscator )
|
||||
{
|
||||
L2PCodeObfuscator *lpco = (L2PCodeObfuscator *)(this->clsObfuscator);
|
||||
if( lpco->isEnabled() )
|
||||
{
|
||||
lpco->encodeOpcode( opcode_RequestActionUse, doubleOpcode );
|
||||
log_error( LOG_DEBUG, "Fix ChangeWaitType2: obfuscated 56 -> %02X\n", opcode_RequestActionUse );
|
||||
}
|
||||
}
|
||||
// create packet
|
||||
L2GamePacket *gp = new L2GamePacket();
|
||||
gp->setPacketType( opcode_RequestActionUse ); //gp->setPacketType( 0x56 ); // opcode :)
|
||||
gp->writeUInt( 0 ); // actionID
|
||||
gp->writeUInt( 0 ); // ctrlPressed
|
||||
gp->writeUChar( 0 ); // shiftPressed
|
||||
(*newLen) = gp->getPacketSize();
|
||||
if( (*newLen) == 0x0C ) // new length must be = 12 bytes
|
||||
{
|
||||
log_error( LOG_OK, "Client: Fixed 36 ChangeWaitType2 OK\n" );
|
||||
bPacketWasModified = true;
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
memcpy( (*newBytes), gp->getBytesPtr(), (*newLen) );
|
||||
}
|
||||
delete gp;
|
||||
}
|
||||
} break;
|
||||
//case 0x39: // RequestMagicSkillUse
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 39 RequestMagicSkillUse\n" );
|
||||
// } break;
|
||||
//case 0x3d: // RequestMagicSkillUse
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 3D RequestShortCutReg\n" );
|
||||
// } break;
|
||||
case 0x48: // RequestTargetCanceld
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Client: 48 RequestTargetCanceld\n" );
|
||||
ai.lockTargetMgr.onUserRequestUnselectTarget();
|
||||
} break;
|
||||
//case 0x57: // RequestRestart
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 57 RequestRestart\n" );
|
||||
// //this->state = GCST_AUTHED;
|
||||
// } break;
|
||||
//case 0x59: // ValidatePosition
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 59 ValidatePosition\n" );
|
||||
// } break;
|
||||
//case 0x65: // RequestPledgeInfo
|
||||
// {
|
||||
// // TODO: parse RequestPledgeInfo?
|
||||
// log_error( LOG_OK, "Client: 65 RequestPledgeInfo\n" );
|
||||
// } break;
|
||||
case 0x8B: // RequestGmList
|
||||
{
|
||||
// RequestGmList kill packet?
|
||||
//log_error( LOG_PACKETNAME, "Client: 8B RequestGmList\n" );
|
||||
if( g_cfg.L2Walker_DropRequestGMList )
|
||||
{
|
||||
log_error( LOG_WARNING, "Client: Droppped RequestGMList!\n" );
|
||||
(*newLen) = (unsigned int)-1; // mark to drop
|
||||
}
|
||||
} break;
|
||||
//case 0xA6: // RequestSkillCoolTime
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: A6 RequestSkillCoolTime\n" );
|
||||
// } break;
|
||||
//case 0xCB: // GameGuardReply
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: CB GameGuardReply\n" );
|
||||
// } break;
|
||||
//case 0xd0:
|
||||
// {
|
||||
// ptype2 = 0x00;
|
||||
// if( len >= 5 )
|
||||
// {
|
||||
// ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
// ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
// switch( ptype2 )
|
||||
// {
|
||||
// case 0x0065: // drop :)
|
||||
// log_error( LOG_WARNING, "Client: Droppped D0:65 (RequestPostItemList in Epilogue)!\n" );
|
||||
// (*newLen) = (unsigned int)-1; // mark to drop
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// log_error( LOG_WARNING, "Client: (IN_GAME) sent 0xD0 without second opcode!\n" );
|
||||
// } break; // double opcode packet
|
||||
//default:
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: Unknown packet %02X in state: IN_GAME\n",
|
||||
// (unsigned int)ptype );
|
||||
// if( g_cfg.DumpUnknownToStdout )
|
||||
// {
|
||||
// printf( "============================================\n" );
|
||||
// L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
// p->dumpToFile( stdout );
|
||||
// delete p;
|
||||
// printf( "============================================\n" );
|
||||
// }
|
||||
// } break;
|
||||
} // switch( ptype )
|
||||
} break; // IN_GAME
|
||||
|
||||
} // switch( state )
|
||||
|
||||
// all encoding takes place ONLY IF PACKET IS NOT SET TO DROP!!!!
|
||||
if( (*newLen) != -1 )
|
||||
{
|
||||
// re-encode packet again =] olny encode original packetif it was not modified
|
||||
//PP_full_reencode_packet( bytes, len, this->key_server_cs );
|
||||
//log_error( LOG_ERROR, "PP_full_reencode_packet() C->S FAILED\n" );
|
||||
if( !bPacketWasModified && this->xor_enabled ) L2GamePacket::encodeXOR_buffer( bytes, len, this->key_server_cs );
|
||||
// if packet was modified, encode only modified packet (encode only that will be sent)
|
||||
if( bPacketWasModified ) L2GamePacket::encodeXOR_buffer( (*newBytes), (*newLen), this->key_server_cs );
|
||||
}
|
||||
else log_error( LOG_PACKETNAME, "Client: No encode - DROP packet!\n" );
|
||||
|
||||
return bPacketWasModified;
|
||||
}
|
||||
873
l2detect/GameClient_full_PP_server.cpp
Normal file
873
l2detect/GameClient_full_PP_server.cpp
Normal file
@@ -0,0 +1,873 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "ProtocolConverter.h"
|
||||
#include "L2PacketTypes.h"
|
||||
#include "RadarDllWnd.h"
|
||||
#include "PacketInjector.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
// Parameters:
|
||||
//
|
||||
// returns true if packet was modified
|
||||
// if packet was not modified:
|
||||
// sets (*newLen) to len;
|
||||
// sets (*newBytes) to bytes
|
||||
// - caller should ignore newLen and newBytes content in this case
|
||||
// - caller should send original packet
|
||||
// if packet was modified:
|
||||
// sets (*newLen) to new length of packet
|
||||
// sets (*newBytes) to point to new bytes buffer
|
||||
// - newBytes are properly encoded if needed,
|
||||
// - caller just should send newBytes and free them after sending
|
||||
// if packet should be dropped:
|
||||
// sets (*newLen) to -1
|
||||
// - caller should ignore newLen and newBytes content
|
||||
// - caller should not send any packet :)
|
||||
//
|
||||
bool GameClient::PP_full_fromServer( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
//
|
||||
(*newBytes) = bytes;
|
||||
(*newLen) = len;
|
||||
//
|
||||
int i = 0;
|
||||
bool bPacketWasModified = false;
|
||||
if( !bytes || len<1 ) return bPacketWasModified;
|
||||
if( len<3 )
|
||||
{
|
||||
log_error( LOG_WARNING, "PP_full_fromServer(): packet len < 3!\n" );
|
||||
return bPacketWasModified;
|
||||
}
|
||||
|
||||
// should we decrypt it?
|
||||
if( this->xor_enabled ) L2GamePacket::decodeXOR_buffer( bytes, len, this->key_server_sc );
|
||||
|
||||
// log packet here, when it is decrypted, if log game packets enabled
|
||||
if( this->logfile ) logPacket( bytes, len, true ); // true - from server
|
||||
|
||||
// parse it
|
||||
unsigned char ptype = bytes[2];
|
||||
unsigned short int ptype2 = 0x0000;
|
||||
unsigned short int ptype3 = 0x0000;
|
||||
if( len >= 5 )
|
||||
{
|
||||
ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
}
|
||||
if( len >= 7 )
|
||||
{
|
||||
ptype3 |= (unsigned short int)(bytes[5] & 0xFFFF);
|
||||
ptype3 |= (unsigned short int)(bytes[6] << 8 & 0xFFFF);
|
||||
}
|
||||
|
||||
// obfuscator
|
||||
class L2PCodeObfuscator *lpco;
|
||||
lpco = (class L2PCodeObfuscator *)this->clsObfuscator;
|
||||
|
||||
// opcode obfuscation is NOT used for Server -> Client packets!
|
||||
/*if( lpco )
|
||||
{
|
||||
if( lpco->isEnabled() && (g_cfg.L2_version != (int)L2_VERSION_T23) )
|
||||
{
|
||||
unsigned char pcode_prev = ptype;
|
||||
unsigned short pcode2_prev = ptype2;
|
||||
bool decode_res = lpco->decodeOpcode( ptype, ptype2, ptype3 );
|
||||
if( decode_res )
|
||||
{
|
||||
if( pcode2_prev == ptype2 )
|
||||
log_error( LOG_DEBUG, "PP_full_fromServer(): de-obfuscated %02X -> %02X\n", pcode_prev, ptype );
|
||||
else
|
||||
log_error( LOG_DEBUG, "PP_full_fromServer(): de-obfuscated %02X:%02X -> %02X:%02X\n",
|
||||
pcode_prev, pcode2_prev, ptype, ptype2 );
|
||||
}
|
||||
else
|
||||
log_error( LOG_ERROR, "PP_full_fromServer(): ERROR de-obfuscating %02X\n", pcode_prev, ptype );
|
||||
}
|
||||
}*/
|
||||
// opcode obfuscation is NOT used for Server -> Client packets!
|
||||
|
||||
L2PacketTypes_LogServer( (L2_VERSION)g_cfg.L2_version, this->state, ptype, ptype2, ptype3 );
|
||||
|
||||
// exception handler block
|
||||
try
|
||||
{
|
||||
|
||||
switch( this->state )
|
||||
{
|
||||
case GCST_CONNECTED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
case 0x2e: // Hellbound: KeyPacket, FirstKey
|
||||
{
|
||||
// check length...
|
||||
if( len < 25 )
|
||||
{
|
||||
log_error( LOG_WARNING, "Received KeyPacket len = %u, but must be 25! Some bot-protection?\n" );
|
||||
log_error( LOG_WARNING, "Or old L2Rebellion-based fucking Java server?\n", len );
|
||||
}
|
||||
// try parse KeyPacket
|
||||
L2Game_KeyPacket *p_key = new L2Game_KeyPacket( bytes, len );
|
||||
p_key->parse();
|
||||
this->opcodeObfuscator = p_key->p_obfuscatorSeed;
|
||||
memcpy( this->key_client_cs, p_key->p_initialKey, 16 );
|
||||
// check allowed proto
|
||||
if( !p_key->p_protocolIsOK ) log_error( LOG_ERROR, "Server tells this protocolVersion is not supported!\n" );
|
||||
delete p_key;
|
||||
// create copies of keys
|
||||
memcpy( this->key_client_sc, this->key_client_cs, sizeof(this->key_client_cs) );
|
||||
memcpy( this->key_server_sc, this->key_client_cs, sizeof(this->key_client_cs) );
|
||||
memcpy( this->key_server_cs, this->key_client_cs, sizeof(this->key_client_cs) );
|
||||
this->xor_enabled = true;
|
||||
log_error( LOG_DEBUGDUMP, "Server: 2e KeyPacket: key: " );
|
||||
for( i=0; i<16; i++ ) log_error_np( LOG_DEBUGDUMP, "%02X ", this->key_client_cs[i] );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
// log obfuscator, if it is != 0x00000000
|
||||
LOG_LEVEL log_level = LOG_DEBUGDUMP;
|
||||
if( this->opcodeObfuscator != 0x00000000 )
|
||||
{
|
||||
log_level = LOG_WARNING;
|
||||
log_error( log_level, "Server: 2e KeyPacket: Obfuscator: 0x%04X\n", this->opcodeObfuscator );
|
||||
// delete obfuscator, if exists
|
||||
if( lpco )
|
||||
{
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
lpco = new L2PCodeObfuscator();
|
||||
lpco->setVersionMode( (L2_VERSION)g_cfg.L2_version );
|
||||
lpco->init_tables( this->opcodeObfuscator );
|
||||
this->clsObfuscator = (void *)lpco;
|
||||
}
|
||||
} break; // KeyPacket
|
||||
case 0x09: // CharacterSelectionInfo // Hellbound
|
||||
{
|
||||
//int nChars = bytes[3];
|
||||
//log_error( LOG_PACKETNAME, "Server: 09 CharacterSelectionInfo: %d chars\n", nChars );
|
||||
this->state = GCST_AUTHED;
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
log_error( LOG_DEBUG, "Server: 09 CharacterSelectionInfo: switch state to AUTHED\n" );
|
||||
} break; // CharacterSelectionInfo
|
||||
//default:
|
||||
// {
|
||||
// LOG_LEVEL log_level = LOG_PACKETNAME;
|
||||
// if( g_cfg.WarnUnknownPacketsToStdout ) log_level = LOG_WARNING;
|
||||
// log_error( log_level, "Server: Unknown packet %02X in state: CONNECTED\n",
|
||||
// (unsigned int)ptype );
|
||||
// if( g_cfg.DumpUnknownToStdout )
|
||||
// {
|
||||
// printf( "============================================\n" );
|
||||
// L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
// p->dumpToFile( stdout );
|
||||
// delete p;
|
||||
// printf( "============================================\n" );
|
||||
// }
|
||||
// } break;
|
||||
} // switch( ptype )
|
||||
} break; // GCST_CONNECTED
|
||||
|
||||
|
||||
case GCST_AUTHED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
case 0x09: // CharacterSelectionInfo // Hellbound
|
||||
{
|
||||
int nChars = bytes[3];
|
||||
log_error( LOG_PACKETNAME, "Server: 09 CharacterSelectionInfo: %d chars\n", nChars );
|
||||
} break; // CharacterSelectionInfo
|
||||
case 0x0b: // CharSelected
|
||||
{
|
||||
this->state = GCST_IN_GAME;
|
||||
log_error( LOG_DEBUG, "Server: 0b CharSelected: switch state from AUTHED to IN_GAME\n" );
|
||||
// parse
|
||||
L2Game_CharSelected *p_charsel = new L2Game_CharSelected( bytes, len );
|
||||
p_charsel->parse();
|
||||
this->opcodeObfuscator = p_charsel->p_opcodeObfuscatorSeed;
|
||||
delete p_charsel;
|
||||
// obfuscator manage
|
||||
if( this->opcodeObfuscator != 0x00000000 )
|
||||
{
|
||||
log_error( LOG_WARNING, "Opcode obfuscation is enabled in CharSelected packet, 0x%08X\n",
|
||||
this->opcodeObfuscator );
|
||||
// delete obfuscator, if exists
|
||||
if( lpco )
|
||||
{
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
lpco = new L2PCodeObfuscator();
|
||||
lpco->setVersionMode( (L2_VERSION)g_cfg.L2_version );
|
||||
lpco->init_tables( this->opcodeObfuscator );
|
||||
this->clsObfuscator = (void *)lpco;
|
||||
}
|
||||
} break;
|
||||
//case 0x0d: // NewCharacterSuccess
|
||||
// {
|
||||
// int nTemplates = bytes[3];
|
||||
// log_error( LOG_PACKETNAME, "Server: 0d NewCharacterSuccess; char_templates: %d\n",
|
||||
// nTemplates );
|
||||
// } break; // NewCharacterSuccess
|
||||
//case 0x0f: // CharCreateOK
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 0f CharCreateOK\n" );
|
||||
// } break; // CharCreateOK
|
||||
//case 0x73: // SSQInfo // Hellbound
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 73 SSQInfo\n" );
|
||||
// // FIXED: SSQInfo should not change client state to IN_GAME, only CharSelected should
|
||||
// //this->state = GCST_IN_GAME;
|
||||
// //this->postNotify( GCN_STATECHANGE, this->state );
|
||||
// } break; // SSQInfo
|
||||
//default:
|
||||
// {
|
||||
// LOG_LEVEL log_level = LOG_PACKETNAME;
|
||||
// if( g_cfg.WarnUnknownPacketsToStdout ) log_level = LOG_WARNING;
|
||||
// log_error( log_level, "Server: Unknown packet %02X in state: AUTHED\n",
|
||||
// (unsigned int)ptype );
|
||||
// if( g_cfg.DumpUnknownToStdout )
|
||||
// {
|
||||
// printf( "============================================\n" );
|
||||
// L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
// p->dumpToFile( stdout );
|
||||
// delete p;
|
||||
// printf( "============================================\n" );
|
||||
// }
|
||||
// } break;
|
||||
} // switch( ptype )
|
||||
} break; // GCST_AUTHED
|
||||
|
||||
|
||||
case GCST_IN_GAME:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
case 0x00: // Die
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 00 Die\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_DIE, bytes, len );
|
||||
} break; // Die
|
||||
case 0x01: // Revive
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 01 Revive\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_REVIVE, bytes, len );
|
||||
} break; // Revive
|
||||
case 0x05: // SpawnItem
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_SPAWNITEM, bytes, len );
|
||||
} break; // SpawnItem
|
||||
case 0x06: // SellList
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true; // it will be encoded again in the end of this function ;)
|
||||
} break; // SellList
|
||||
case 0x07: // BuyList
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true; // it will be encoded again in the end of this function ;)
|
||||
} break; // BuyList
|
||||
case 0x08: // DeleteObject
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 08 DeleteObject\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_DELETEOBJECT, bytes, len );
|
||||
} break; // DeleteObject
|
||||
case 0x0b: // CharSelected (must be in AUTHED state, but it fixes problem on some L2J servers that do not send SSQInfo packet)
|
||||
{
|
||||
this->state = GCST_IN_GAME;
|
||||
log_error( LOG_DEBUG, "Server: 0b CharSelected: switch state from IN_GAME to IN_GAME\n" );
|
||||
// parse
|
||||
L2Game_CharSelected *p_charsel = new L2Game_CharSelected( bytes, len );
|
||||
p_charsel->parse();
|
||||
this->opcodeObfuscator = p_charsel->p_opcodeObfuscatorSeed;
|
||||
delete p_charsel;
|
||||
// obfuscator manage
|
||||
if( this->opcodeObfuscator != 0x00000000 )
|
||||
{
|
||||
log_error( LOG_WARNING, "Opcode obfuscation is enabled in CharSelected packet, 0x%08X\n",
|
||||
this->opcodeObfuscator );
|
||||
// delete obfuscator, if exists
|
||||
if( lpco )
|
||||
{
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
lpco = new L2PCodeObfuscator();
|
||||
lpco->setVersionMode( (L2_VERSION)g_cfg.L2_version );
|
||||
lpco->init_tables( this->opcodeObfuscator );
|
||||
this->clsObfuscator = (void *)lpco;
|
||||
}
|
||||
} break;
|
||||
case 0x0c: // NpcInfo (mob) [CharInfo morphed]?
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 0c NpcInfo\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_NPCINFO, bytes, len );
|
||||
} break;
|
||||
case 0x11: // ItemList
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 11 ItemList\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_ITEMLIST, bytes, len );
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true; // it will be encoded again in the end of this function ;)
|
||||
} break; // ItemList
|
||||
//case 0x12: // SunRise
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 12 SunRise\n" );
|
||||
// } break;
|
||||
case 0x14: // TradeStart
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // TradeStart
|
||||
case 0x16: // DropItem
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_DROPITEM, bytes, len );
|
||||
} break;
|
||||
//case 0x17: // GetItem
|
||||
// {
|
||||
// // TODO: Items handling
|
||||
// log_error( LOG_USERAI, "Server: 17 GetItem\n" );
|
||||
// } break;
|
||||
case 0x18: // StatusUpdate
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_STATUSUPDATE, bytes, len );
|
||||
} break; // StatusUpdate
|
||||
case 0x19: // NpcHtmlMessage
|
||||
{
|
||||
ai.UAI_process_NpcHtml( bytes, len );
|
||||
} break; // NpcHtmlMessage
|
||||
case 0x1A: // TradeOwnAdd
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // TradeOwnAdd
|
||||
case 0x1B: // TradeOtherAdd
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // TradeOtherAdd
|
||||
//case 0x1F: // ActionFailed
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 1F ActionFailed\n" );
|
||||
// } break; // ActionFailed
|
||||
case 0x21: // InventoryUpdate
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_INVENTORYUPDATE, bytes, len );
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true; // it will be encoded again in the end of this function ;)
|
||||
} break; // InventoryUpdate
|
||||
case 0x22: // TeleportToLocation
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_TELEPORTTOLOCATION, bytes, len );
|
||||
} break; // TeleportToLocation
|
||||
case 0x23: // TargetSelected
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_TARGETSELECTED, bytes, len );
|
||||
} break; // TargetSelected
|
||||
case 0x24: // TargetUnselected
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_TARGETUNSELECTED, bytes, len );
|
||||
} break; // TargetUnselected
|
||||
//case 0x25: // AutoAttackStart
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 25 AutoAttackStart\n" );
|
||||
// } break; // AutoAttackStart
|
||||
//case 0x26: // AutoAttackStop
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 26 AutoAttackStop\n" );
|
||||
// } break; // AutoAttackStop
|
||||
//case 0x27: // SocialAction
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 27 SocialAction\n" );
|
||||
// } break; // SocialAction
|
||||
case 0x28: // ChangeMoveType
|
||||
{
|
||||
ai.UAI_process_ChangeMoveType( bytes, len );
|
||||
} break; // ChangeMoveType
|
||||
case 0x29: // ChangeWaitType
|
||||
{
|
||||
ai.UAI_process_ChangeWaitType( bytes, len );
|
||||
} break; // ChangeWaitType
|
||||
case 0x2f: // MoveToLocation
|
||||
{
|
||||
// some pc/npc moves, also user (player) moves possibly
|
||||
//log_error( LOG_PACKETNAME, "Server: 2f MoveToLocation\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_MOVETOLOCATION, bytes, len );
|
||||
} break; // MoveToLocation
|
||||
//case 0x30: // NpcSay
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 30 NpcSay\n" );
|
||||
// } break; // NpcSay
|
||||
case 0x31: // CharInfo
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 31 CharInfo\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_CHARINFO, bytes, len );
|
||||
} break; // CharInfo
|
||||
case 0x32: // UserInfo
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 32 UserInfo\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_USERINFO, bytes, len );
|
||||
} break; // UserInfo
|
||||
//case 0x33: // Attack
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 33 Attack\n" );
|
||||
// //ai.notifyEventPacket( UAI_PEVENT_ATTACK, bytes, len );
|
||||
// } break;
|
||||
//case 0x41: // WareHouseDepositList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 41 WareHouseDepositList\n" );
|
||||
// // TODO: protocol convert WareHouseDepositList
|
||||
// } break;
|
||||
//case 0x42: // WareHouseWithdrawalList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 42 WareHouseWithdrawalList\n" );
|
||||
// // TODO: protocol convert WareHouseWithdrawalList
|
||||
// } break;
|
||||
//case 0x44: // ShortCutRegister
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 44 ShortCutRegister\n" );
|
||||
// } break; // ShortCutRegister
|
||||
//case 0x45: // ShortCutInit
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 45 ShortCutInit\n" );
|
||||
// } break; // ShortCutInit
|
||||
case 0x47: // StopMove
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_STOPMOVE, bytes, len );
|
||||
} break;
|
||||
case 0x48: // MagicSkillUse
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_MAGICSKILLUSE, bytes, len );
|
||||
} break; // MagicSkillUse
|
||||
case 0x49: // MagicSkillCanceld
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_MAGICSKILLCANCELLED, bytes, len );
|
||||
} break; // MagicSkillCanceld
|
||||
//case 0x4A: // CreatureSay
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 4A CreatureSay\n" );
|
||||
// // TODO: CreatureSay parse
|
||||
// } break; // CreatureSay
|
||||
case 0x41: // WarehouseDepositList
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // WarehouseDepositList
|
||||
case 0x42: // WarehouseWithdrawList
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // WarehouseWithdrawList
|
||||
//case 0x4C: // DoorInfo
|
||||
// {
|
||||
// log_error( LOG_OK, "DoorInfo\n" );
|
||||
// } break; // DoorInfo
|
||||
//case 0x4D: // DoorStatusUpdate
|
||||
// {
|
||||
// log_error( LOG_OK, "DoorStatusUpdate\n" );
|
||||
// } break; // DoorStatusUpdate
|
||||
case 0x4E: // PartySmallWindowAll
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_PARTYALL, bytes, len );
|
||||
} break; // PartySmallWindowAll
|
||||
case 0x4F: // PartySmallWindowAdd
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_PARTYADD, bytes, len );
|
||||
} break; // PartySmallWindowAdd
|
||||
case 0x50: // PartySmallWindowDeleteAll
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_PARTYDELALL, bytes, len );
|
||||
} break; // PartySmallWindowDeleteAll
|
||||
case 0x51: // PartySmallWindowDelete
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_PARTYDEL, bytes, len );
|
||||
} break; // PartySmallWindowDelete
|
||||
case 0x52: // PartySmallWindowUpdate
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_PARTYUPDATE, bytes, len );
|
||||
} break; // PartySmallWindowUpdate
|
||||
//case 0x54: // MagicSkillLaunched
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 54 MagicSkillLaunched\n" );
|
||||
// L2GamePacket *msl = new L2GamePacket();
|
||||
// msl->setBytes( bytes, len );
|
||||
// msl->readReset();
|
||||
// msl->getPacketType();
|
||||
// unsigned int oid = msl->readUInt(); // caster id
|
||||
// int skillId = msl->readD(); // skill id
|
||||
// int skillLvl = msl->readD(); // skill lvl
|
||||
// delete msl;
|
||||
// if( oid == this->ai.usr.objectID )
|
||||
// {
|
||||
// log_error_np( LOG_OK, "You launched skill %d lvl %d\n", skillId, skillLvl );
|
||||
// }
|
||||
// } break; // MagicSkillLaunched
|
||||
//case 0x5A: // PledgeShowMemberListAll
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5A PledgeShowMemberListAll\n" );
|
||||
// } break; // PledgeShowMemberListAll
|
||||
//case 0x5B: // PledgeShowMemberListUpdate
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5B PledgeShowMemberListUpdate\n" );
|
||||
// } break; // PledgeShowMemberListUpdate
|
||||
//case 0x5C: // PledgeShowMemberListAdd
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5C PledgeShowMemberListAdd\n" );
|
||||
// } break; // PledgeShowMemberListAdd
|
||||
case 0x5F: // SkillList
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_SKILLLIST, bytes, len );
|
||||
} break; // SkillList
|
||||
//case 0x62: // SystemMessage
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 62 SystemMessage\n" );
|
||||
// } break; // SystemMessage
|
||||
case 0x6b: // SetupGauge
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_SETUPGAUGE, bytes, len );
|
||||
} break; // SetupGauge
|
||||
//case 0x6c: // VehicleDeparture
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 6C VehicleDeparture\n" );
|
||||
// } break;
|
||||
//case 0x72: // MoveToPawn
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 72 MoveToPawn\n" );
|
||||
// } break; // MoveToPawn
|
||||
case 0x71: // RestartResponse (RestartOK)
|
||||
{
|
||||
L2GamePacket *pack = new L2GamePacket( bytes, len );
|
||||
pack->getPacketType(); // 0x71
|
||||
int restartOK = pack->readD();
|
||||
if( restartOK == 0x01 )
|
||||
{
|
||||
// notify user AI that user is not in game
|
||||
ai.userLogout();
|
||||
//log_error( LOG_PACKETNAME, "Server: 71 RestartResponse (RestartOK)\n" );
|
||||
this->state = GCST_AUTHED;
|
||||
log_error( LOG_DEBUG, "Server: 71 RestartResponse: switch state to AUTHED\n" );
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
}
|
||||
else
|
||||
log_error( LOG_USERAI, "RestartResponse: logout failed!\n" );
|
||||
delete pack;
|
||||
} break; // RestartResponse
|
||||
case 0x74: // GameGuardQuery
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 74 GameGuardQuery\n" );
|
||||
// if enabled, radar can emulate GameGuard reply to standard L2J Query
|
||||
if( g_cfg.ReplyL2JGameGuardQuery )
|
||||
{
|
||||
L2GamePacket *pack = new L2GamePacket( bytes, len );
|
||||
pack->getPacketType();
|
||||
unsigned int q1 = pack->readUInt();
|
||||
unsigned int q2 = pack->readUInt();
|
||||
unsigned int q3 = pack->readUInt();
|
||||
unsigned int q4 = pack->readUInt();
|
||||
delete pack;
|
||||
pack = NULL;
|
||||
// parse request
|
||||
if( q1 == 0x27533DD9 && q2 == 0x2E72A51D && q3 == 0x2017038B && q4 == 0xC35B1EA3 )
|
||||
{
|
||||
log_error( LOG_WARNING, "Received standard l2J GameGuardQuery, replying :)\n" );
|
||||
// reply with well known answer
|
||||
PGen_GameGuardReply_L2J();
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_WARNING, "Received unknown GameGuardQuery 0x%08X 0x%08X 0x%08X 0x%08X!\n",
|
||||
q1, q2, q3, q4 );
|
||||
// do nothing...
|
||||
}
|
||||
} // if( g_cfg.ReplyL2JGameGuardQuery )
|
||||
} break; // GameGuardQuery
|
||||
//case 0x75: // FriendList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 75 FriendList\n" );
|
||||
// } break; // FriendList
|
||||
//case 0x79: // ValidateLocation
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 79 ValidateLocation\n" );
|
||||
// } break; // ValidateLocation
|
||||
//case 0x7B: // ShowBoard
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 7B ShowBoard\n" );
|
||||
// } break; // ShowBoard
|
||||
case 0x84: // LeaveWorld
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 84 LeaveWorld\n" );
|
||||
// simple trigger
|
||||
ai.userLogout();
|
||||
} break; // LeaveWorld
|
||||
case 0x85: // AbnormalStatusUpdate
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_ABNORMALSTATUSUPDATE, bytes, len );
|
||||
} break; // AbnormalStatusUpdate
|
||||
//case 0x86: // QuestList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 86 QuestList\n" );
|
||||
// } break; // QuestList
|
||||
case 0x89: // PledgeInfo
|
||||
{
|
||||
// writeC(0x89);
|
||||
// writeD(_clan.getClanId());
|
||||
// writeS(_clan.getName());
|
||||
// writeS(_clan.getAllyName());
|
||||
unsigned int clanID = bytes[3] | (bytes[4] << 8) | (bytes[5] << 16) | (bytes[6] << 24);
|
||||
//wchar_t clan_name[128] = {0};
|
||||
//wchar_t ally_name[128] = {0};
|
||||
unsigned int offset = 7; // 2(plen) + 1(pcode) + 4(clanID);
|
||||
//wcscpy( clan_name, (const wchar_t *)(bytes + offset) ); // wcscpy is too slow...
|
||||
const wchar_t *clan_name = (const wchar_t *)( bytes + offset );
|
||||
offset += wcslen( clan_name ) * 2 + 2; // now we can read ally_name from offset
|
||||
//wcscpy( ally_name, (const wchar_t *)(bytes + offset) ); // wcscpy is too slow...
|
||||
const wchar_t *ally_name = (const wchar_t *)( bytes + offset );
|
||||
ClanList_Add( clanID, clan_name, ally_name );
|
||||
log_error( LOG_PACKETNAME, "Server: 89 PledgeInfo %u [%S] Ally: [%S]\n",
|
||||
clanID, clan_name, ally_name );
|
||||
RadarWnd_ForceUpdateCharsList(); // force update chars list
|
||||
} break; // PledgeInfo
|
||||
//case 0x8C: // Ride
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 8C Ride\n" );
|
||||
// } break; // Ride
|
||||
//case 0x9F: // StaticObject
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 9F StaticObject\n" );
|
||||
// L2GamePacket *so = new L2GamePacket();
|
||||
// so->setBytes( bytes, len );
|
||||
// so->getPacketType(); // read 0x9F
|
||||
// unsigned int staticObjectID = so->readUInt();
|
||||
// unsigned int objectID = so->readUInt();
|
||||
// unsigned int soType = so->readUInt();
|
||||
// so->readUInt();
|
||||
// so->readUInt();
|
||||
// unsigned int isClosed = so->readUInt();
|
||||
// so->readUInt();
|
||||
// int curHp = so->readInt();
|
||||
// int maxHp = so->readInt();
|
||||
// if( soType == 1 ) // this is door
|
||||
// {
|
||||
// char dooropen[32];
|
||||
// strcpy( dooropen, "OPEN" );
|
||||
// if( isClosed ) strcpy( dooropen, "CLOSED" );
|
||||
// log_error_np( LOG_OK, "Door id [%u] objectId [%u] is %s (HP %d / %d)\n",
|
||||
// staticObjectID, objectID, dooropen, curHp, maxHp );
|
||||
// }
|
||||
// else log_error_np( LOG_OK, "StaticObject %u is not door\n", staticObjectID );
|
||||
// delete so;
|
||||
// } break; // StaticObject
|
||||
case 0xA1: // PrivateStoreListSell
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: A1 PrivateStoreListSell\n" );
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // PrivateStoreListSell
|
||||
//case 0xA2: // PrivateStoreMsgSell
|
||||
// {
|
||||
// //log_error( LOG_PACKETNAME, "Server: A2 PrivateStoreMsgSell\n" );
|
||||
// } break; // PrivateStoreMsgSell
|
||||
case 0xB9: // MyTargetSelected
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: B9 MyTargetSelected [%u]\n", objectID );
|
||||
ai.notifyEventPacket( UAI_PEVENT_MYTARGETSELECTED, bytes, len );
|
||||
} break; // MyTargetSelected
|
||||
case 0xBE: // PrivateStoreListBuy
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: BE PrivateStoreListBuy\n" );
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true;
|
||||
} break; // PrivateStoreListBuy
|
||||
//case 0xBF: // PrivateStoreMsgBuy
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: BF PrivateStoreMsgBuy\n" );
|
||||
// } break; // PrivateStoreMsgBuy
|
||||
case 0xC7: // SkillCoolTime
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_SKILLCOOLTIME, bytes, len );
|
||||
} break; // SkillCoolTime
|
||||
//case 0xCD: // PledgeStatusChanged
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: CD PledgeStatusChanged\n" );
|
||||
// } break; // PledgeStatusChanged
|
||||
case 0xCE: // RelationChanged
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: CE RelationChanged\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_RELATIONCHANGED, bytes, len );
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true; // it will be encoded again in the end of this function ;)
|
||||
} break; // RelationChanged
|
||||
//case 0xE5: // HennaInfo
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: E5 HennaInfo\n" );
|
||||
// } break; // HennaInfo
|
||||
//case 0xE8: // SendMacroList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: E8 SendMacroList\n" );
|
||||
// } break; // SendMacroList
|
||||
//case 0xF2: // ClientSetTime
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: F2 ClientSetTime\n" );
|
||||
// } break; // ClientSetTime
|
||||
case 0xF4: // PartySpelled
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_PARTYSPELLED, bytes, len );
|
||||
} break;
|
||||
//case 0xF9: // EtcStatusUpdate
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: F9 EtcStatusUpdate\n" );
|
||||
// } break; // EtcStatusUpdate
|
||||
case 0xFA: // ShortBuffStatusUpdate
|
||||
{
|
||||
ai.notifyEventPacket( UAI_PEVENT_SHORTBUFFSTATUSUPDATE, bytes, len );
|
||||
} break; // ShortBuffStatusUpdate
|
||||
//case 0xFD: // AgitDecoInfo
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FD AgitDecoInfo\n" );
|
||||
// } break; // AgitDecoInfo
|
||||
case 0xFE: // double-byte packet
|
||||
{
|
||||
ptype2 = 0x00;
|
||||
if( len >= 5 )
|
||||
{
|
||||
ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
switch( ptype2 )
|
||||
{
|
||||
//case 0x01: // ExRegenMax
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:01 ExRegenMax\n" );
|
||||
// } break;
|
||||
//case 0x0c: // ExAutoSoulShot FE:0C
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:0C ExAutoSoulShot\n" );
|
||||
// } break;
|
||||
//case 0x22: // ExSendManorList FE:22
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:22 ExSendManorList\n" );
|
||||
// } break;
|
||||
//case 0x2f: // ExStorageMaxCount FE:2f
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:2F ExStorageMaxCount\n" );
|
||||
// } break;
|
||||
//case 0x32: // ExPCCafePointInfo FE:32
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:32 ExPCCafePointInfo\n" );
|
||||
// } break;
|
||||
//case 0x33: // ExSetCompassZoneCode FE:33
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:33 ExSetCompassZoneCode\n" );
|
||||
// } break;
|
||||
//case 0x3a: // PledgeSkillList FE:3A
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:3A PledgeSkillList\n" );
|
||||
// } break;
|
||||
case 0x3f: // PledgeReceiveWarList FE:3F
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Server: FE:3F PledgeReceiveWarList\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_PLEDGERECEIVEWARLIST, bytes, len );
|
||||
} break;
|
||||
//case 0x40: // PledgeReceiveSubPledgeCreated FE:40
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:40 PledgeReceiveSubPledgeCreated\n" );
|
||||
// } break;
|
||||
//case 0x5f: // ExBasicActionList FE:5F
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:5F ExBasicActionList\n" );
|
||||
// } break;
|
||||
case 0x8D: // Gracia Final FE:8D ExNpcQuestHtmlMessage
|
||||
{
|
||||
if( g_cfg.L2_version >= (int)L2_VERSION_T23 )
|
||||
ai.UAI_process_NpcHtml( bytes, len );
|
||||
} break;
|
||||
//case 0xAC: // possibly old ExBrExtraUserInfo
|
||||
// {
|
||||
// log_error( LOG_WARNING, "[PACK] possibly old ExBrExtraUserInfo FE:AC\n" );
|
||||
// } break; // possibly old ExBrExtraUserInfo
|
||||
case 0xB7: // ExBuySellListPacket
|
||||
{
|
||||
if( ProtoConv_IsEnabled() )
|
||||
if( ProtoConv_ConvertPacket( bytes, len, newBytes, newLen ) )
|
||||
bPacketWasModified = true; // it will be encoded again in the end of this function ;)
|
||||
} break; // ExBuySellListPacket
|
||||
//default: log_error( LOG_PACKETNAME, "Server: Unknown opcode2 %04X for IN_GAME packet 0xFE\n",
|
||||
// (unsigned int)ptype2 ); break;
|
||||
}
|
||||
}
|
||||
else log_error( LOG_WARNING, "Server: (IN_GAME) sent 0xFE without second opcode!\n" );
|
||||
} break; // double-byte packet
|
||||
//default:
|
||||
// {
|
||||
// LOG_LEVEL log_level = LOG_PACKETNAME;
|
||||
// if( g_cfg.WarnUnknownPacketsToStdout ) log_level = LOG_WARNING;
|
||||
// log_error( log_level, "Server: Unknown packet %02X in state: IN_GAME\n",
|
||||
// (unsigned int)ptype );
|
||||
// if( g_cfg.DumpUnknownToStdout )
|
||||
// {
|
||||
// printf( "============================================\n" );
|
||||
// L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
// p->dumpToFile( stdout );
|
||||
// delete p;
|
||||
// printf( "============================================\n" );
|
||||
// }
|
||||
// } break;
|
||||
} // switch( ptype )
|
||||
} break; // GCST_IN_GAME
|
||||
} // switch( state )
|
||||
|
||||
} // try
|
||||
catch( L2P_Exception& e )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2P_Exception in PP_full_fromServer\n", e.what() );
|
||||
}
|
||||
|
||||
// all encoding takes place ONLY IF PACKET IS NOT SET TO DROP!!!!
|
||||
if( (*newLen) != -1 )
|
||||
{
|
||||
// re-encode packet again, independently if it was modified or not.
|
||||
// ... BUT NEVER ENCODE KeyPacket 0x2E! (though XOR is enabled now)
|
||||
// this encodes only original unmodified packet!!!
|
||||
if( (bPacketWasModified == false) && (ptype != 0x2e) )
|
||||
{
|
||||
//PP_full_reencode_packet( bytes, len, this->key_client_sc );
|
||||
//log_error( LOG_ERROR, "PP_full_reencode_packet() FAILED\n" );
|
||||
//log_error( LOG_OK, "Encoding unmodified packet\n" );
|
||||
if( this->xor_enabled ) L2GamePacket::encodeXOR_buffer( bytes, len, this->key_client_sc );
|
||||
}
|
||||
// encode only modified packet, if packet was modified
|
||||
if( bPacketWasModified == true )
|
||||
{
|
||||
// log modified packet here, when it is decrypted, if log game packets enabled
|
||||
if( this->logfile )
|
||||
{
|
||||
fprintf( this->logfile, "Next is modified:\n" );
|
||||
logPacket( (*newBytes), (*newLen), true ); // true - from server
|
||||
}
|
||||
|
||||
//log_error( LOG_OK, "Encoding modified packet\n" ); // <==DEL
|
||||
if( this->xor_enabled ) L2GamePacket::encodeXOR_buffer( (*newBytes), (*newLen), this->key_client_sc );
|
||||
}
|
||||
}
|
||||
//else log_error( LOG_OK, "Server: No encode - DROP packet!\n" );
|
||||
|
||||
return bPacketWasModified;
|
||||
}
|
||||
78
l2detect/GameClient_full_injectPacket.cpp
Normal file
78
l2detect/GameClient_full_injectPacket.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
|
||||
extern CConfig g_cfg;
|
||||
|
||||
// TODO: count obfuscator
|
||||
|
||||
bool GameClient::InjectPacketToServer( unsigned char *bytes, unsigned int len, bool doObfuscate )
|
||||
{
|
||||
if( !bytes || (len<3) ) return false;
|
||||
if( this->sock_server == INVALID_SOCKET ) return false;
|
||||
if( g_cfg.EnableModifyGameTraffic == 0 ) return false; // FIXED: do not allow traffic modification if not set
|
||||
if( this->state == GCST_OFFLINE )
|
||||
log_error( LOG_WARNING, "GameClient::InjectPacketToServer(): trying to send packet to server in state GCST_OFFLINE!\n" );
|
||||
unsigned int sentLen = 0;
|
||||
// TODO: obfuscate opcode before sending?
|
||||
if( doObfuscate )
|
||||
{
|
||||
if( (this->opcodeObfuscator != 0x00) && (this->clsObfuscator) )
|
||||
{
|
||||
L2PCodeObfuscator *obf = (L2PCodeObfuscator *)(this->clsObfuscator);
|
||||
unsigned char singleOpcode = bytes[2];
|
||||
unsigned short doubleOpcode = bytes[3] | (bytes[4] << 8);
|
||||
unsigned short tripleOpcode = bytes[5] | (bytes[6] << 8);
|
||||
unsigned char prev_singleOpcode = singleOpcode;
|
||||
unsigned short prev_doubleOpcode = doubleOpcode;
|
||||
try
|
||||
{
|
||||
obf->encodeOpcode( singleOpcode, doubleOpcode, tripleOpcode );
|
||||
}
|
||||
catch( L2P_ObfuscateException& e )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::InjectPacketToServer: ObfuscationException: %s\n", e.what() );
|
||||
}
|
||||
// log
|
||||
if( prev_doubleOpcode == doubleOpcode )
|
||||
log_error( LOG_PACKETNAME, "InjectPacketToServer: obfuscated %02X -> %02X\n",
|
||||
singleOpcode, prev_singleOpcode );
|
||||
else
|
||||
log_error( LOG_PACKETNAME, "InjectPacketToServer: obfuscated %02X:%02X -> %02X:%02X\n",
|
||||
singleOpcode, doubleOpcode, prev_singleOpcode, prev_doubleOpcode );
|
||||
// replace bytes in packet
|
||||
bytes[2] = singleOpcode;
|
||||
bytes[3] = doubleOpcode & 0xFF;
|
||||
bytes[4] = (doubleOpcode >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
// encode XOR if enabled
|
||||
if( this->xor_enabled ) L2GamePacket::encodeXOR_buffer( bytes, len, this->key_server_cs );
|
||||
LockSend();
|
||||
//int ret = L2PacketSend( bytes, sock_server, 5, 0, &sentLen );
|
||||
//int ret = L2PacketSend2( bytes, sock_server, 5000, &sentLen );
|
||||
L2PacketSend2( bytes, sock_server, 5000, &sentLen );
|
||||
UnlockSend();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameClient::InjectPacketToClient( unsigned char *bytes, unsigned int len )
|
||||
{
|
||||
if( !bytes || (len<3) ) return false;
|
||||
if( this->sock_client == INVALID_SOCKET ) return false;
|
||||
if( g_cfg.EnableModifyGameTraffic == 0 ) return false; // FIXED: do not allow traffic modification if not set
|
||||
if( this->state == GCST_OFFLINE )
|
||||
log_error( LOG_WARNING, "GameClient::InjectPacketToClient(): trying to send packet to client in state GCST_OFFLINE!\n" );
|
||||
unsigned int sentLen = 0;
|
||||
if( this->xor_enabled )
|
||||
{
|
||||
L2GamePacket::encodeXOR_buffer( bytes, len, this->key_client_sc );
|
||||
}
|
||||
LockSend();
|
||||
int ret = L2PacketSend2( bytes, sock_client, 5000, &sentLen );
|
||||
UnlockSend();
|
||||
if( ret <= 0 ) log_error( LOG_ERROR, "InjectPacketToClient: send failed (sent %u bytes)\n", sentLen );
|
||||
return true;
|
||||
}
|
||||
273
l2detect/GameClient_sniff.cpp
Normal file
273
l2detect/GameClient_sniff.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "CharArray.h"
|
||||
#include "ClanList.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
extern class GameListener *g_pgame;
|
||||
|
||||
bool GameClient::PC_sniff( SOCKET scl, unsigned char *sip, unsigned short int sport )
|
||||
{
|
||||
sock_client = INVALID_SOCKET;
|
||||
sock_server = INVALID_SOCKET;
|
||||
this->resetCounters( false );
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_onlySniff() started\n" );
|
||||
// assert
|
||||
if( (scl == INVALID_SOCKET) || (!sip) || (sport<1) )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::ProcessClient_onlySniff(): start assert failed\n" );
|
||||
return false;
|
||||
}
|
||||
// vars
|
||||
bool retVal = false;
|
||||
SOCKET sg = INVALID_SOCKET;
|
||||
char ssip[16] = {0};
|
||||
sprintf( ssip, "%d.%d.%d.%d", (int)sip[0], (int)sip[1], (int)sip[2], (int)sip[3] );
|
||||
|
||||
// first we should connect to real game server
|
||||
// create real GS socket
|
||||
sg = L2PNet_TCPsocket_create( true );
|
||||
if( sg == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::ProcessClient_onlySniff(): real GS socket create\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// connect to real game server
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_onlySniff(): Connecting to real game server %s:%d ", ssip, (int)sport );
|
||||
L2PNet_connect( sg, ssip, sport );
|
||||
int nTries = 20;
|
||||
int r = 0;
|
||||
while( nTries > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, "." );
|
||||
r = L2PNet_select( sg, L2PNET_SELECT_WRITE, 500, NULL, NULL );
|
||||
if( r == 1 ) break;
|
||||
nTries--;
|
||||
}
|
||||
|
||||
log_error_np( LOG_DEBUG, "\n" );
|
||||
if( r == 1 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_onlySniff(): Connected. Tries left: %d\n", nTries );
|
||||
}
|
||||
else
|
||||
{
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_onlySniff(): Not connected.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// open log file
|
||||
if( g_cfg.LogGamePackets )
|
||||
{
|
||||
char filename[256];
|
||||
char filename_raw[256];
|
||||
time_t nowTime;
|
||||
time( &nowTime );
|
||||
sprintf( filename, "%s%u.txt",
|
||||
g_cfg.LogGameFileNamePrefix,
|
||||
(unsigned int)nowTime );
|
||||
sprintf( filename_raw, "%s%u_raw.txt",
|
||||
g_cfg.LogGameFileNamePrefix,
|
||||
(unsigned int)nowTime );
|
||||
this->logfile = fopen( filename, "wt" );
|
||||
if( !logfile )
|
||||
log_error( LOG_WARNING, "GameClient::ProcessClient_onlySniff(): Cannot open log file [%s] for writing!\n",
|
||||
filename );
|
||||
// open raw log data for not decrypted packets, if problems with decryption
|
||||
// this->logfileRaw = fopen( filename_raw, "wt" );
|
||||
}
|
||||
|
||||
// set initial game client state
|
||||
this->state = GCST_CONNECTED;
|
||||
this->sock_client = scl;
|
||||
this->sock_server = sg;
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
this->counters.startTimer();
|
||||
ai.notifyEvent( UAI_EVENT_START );
|
||||
|
||||
// infinite loop
|
||||
int recvTimeout = 20; // seconds
|
||||
long recvTimeoutMsec = recvTimeout * 1000;
|
||||
int selectTimeout = 1; // seconds
|
||||
struct timeval tv;
|
||||
fd_set fdReadSet;
|
||||
unsigned char *p = NULL;
|
||||
unsigned int rcvdLen = 0;
|
||||
unsigned int sentLen = 0;
|
||||
unsigned int scode = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
// first check are we signaled to exit?
|
||||
scode = g_pgame->getLastSignal();
|
||||
if( scode == FLGS_STOP )
|
||||
{
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_onlySniff(): exit signal\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
tv.tv_sec = selectTimeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// check readability on sockets
|
||||
FD_ZERO( &fdReadSet ); // zero set
|
||||
FD_SET( scl, &fdReadSet ); // add client socket to read set
|
||||
FD_SET( sg, &fdReadSet ); // add real GS socket to read set
|
||||
//r = select( 0, &fdReadSet, 0, 0, &tv );
|
||||
r = L2PNet_select_wrapper_DUMB( 0, &fdReadSet, 0, 0, &tv );
|
||||
if( r == 0 ) /* timeout failed */
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "." );
|
||||
}
|
||||
else if( r == -1 ) /* select error */
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "\nselect() ERROR\n" );
|
||||
// TODO: what to do on select() error?
|
||||
//int wsaerr = WSAGetLastError();
|
||||
int wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock error: " );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
//log_error( LOG_ERROR, "ProcessClient_onlySniff(): socket select() ERROR!\n" );
|
||||
//log_error( LOG_ERROR, "ProcessClient_onlySniff(): closing processing\n" );
|
||||
//goto netError;
|
||||
}
|
||||
else if( r > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "\nselect(): number of sockets ready: %d\n", r );
|
||||
if( L2PNet_FD_ISSET( scl, &fdReadSet ) ) // client sent something?
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "C->S (reading...)\n" );
|
||||
// first receive packet from client
|
||||
p = L2PacketReceive_malloc( scl, recvTimeoutMsec, &rcvdLen );
|
||||
log_error( LOG_DEBUGDUMP, "Received %u bytes from client\n", rcvdLen );
|
||||
if( p && (rcvdLen == 0) )
|
||||
{
|
||||
log_error( LOG_WARNING, "Connection closed by client?\n" );
|
||||
goto closeSocks;
|
||||
}
|
||||
if( !p )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2PacketReceive() failed!\n" );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// counters
|
||||
this->counters.addSentPacket( rcvdLen );
|
||||
|
||||
// ... then resend packet to server
|
||||
r = L2PacketSend2( p, sg, recvTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUGDUMP, "Sent %u bytes to server\n", sentLen );
|
||||
if( rcvdLen != sentLen )
|
||||
{
|
||||
log_error( LOG_ERROR, "sent != rcvd!!! (%u != %u)\n", sentLen, rcvdLen );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// log raw bytes, before decode
|
||||
logPacketRaw( p, rcvdLen, false );
|
||||
// ... and only then process this packet
|
||||
PP_sniff_fromClient( p, rcvdLen );
|
||||
logPacket( p, rcvdLen, false );
|
||||
free( p );
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
if( L2PNet_FD_ISSET( sg, &fdReadSet ) ) // server sent something?
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "S->C (reading...)\n" );
|
||||
// first receive packet from server
|
||||
p = L2PacketReceive_malloc( sg, recvTimeoutMsec, &rcvdLen );
|
||||
log_error( LOG_DEBUGDUMP, "Received %u bytes from server\n", rcvdLen );
|
||||
if( p && (rcvdLen == 0) )
|
||||
{
|
||||
log_error( LOG_WARNING, "Connection closed by server?\n" );
|
||||
goto closeSocks;
|
||||
}
|
||||
if( !p )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2PacketReceive() failed!\n" );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// counters
|
||||
this->counters.addRcvdPacket( rcvdLen );
|
||||
|
||||
// .. then resend packet to client
|
||||
r = L2PacketSend2( p, scl, recvTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUGDUMP, "Sent %u bytes to client\n", sentLen );
|
||||
if( rcvdLen != sentLen )
|
||||
{
|
||||
log_error( LOG_ERROR, "sent != rcvd!!! (%u != %u)\n", sentLen, rcvdLen );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// log raw bytes, before decode
|
||||
logPacketRaw( p, rcvdLen, true );
|
||||
// ... and only then process it
|
||||
PP_sniff_fromServer( p, rcvdLen );
|
||||
logPacket( p, rcvdLen, true );
|
||||
free( p );
|
||||
p = NULL;
|
||||
}
|
||||
} // (r>0) // select() OK
|
||||
}// while(1)
|
||||
|
||||
retVal = true;
|
||||
netError:
|
||||
log_error( LOG_ERROR, "PC_sniff(): some error happened or network connection closed...\n" );
|
||||
if( p ) free( p );
|
||||
p = NULL;
|
||||
retVal = false;
|
||||
closeSocks: // all cleanup
|
||||
// logfile
|
||||
if( this->logfile )
|
||||
{
|
||||
fclose( this->logfile );
|
||||
this->logfile = NULL;
|
||||
}
|
||||
// stop AI thread
|
||||
ai.notifyEvent( UAI_EVENT_STOP );
|
||||
this->resetConnectedState();
|
||||
// sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
// lists
|
||||
CharArray_DeleteAll();
|
||||
ClanList_DeleteAll();
|
||||
// state
|
||||
this->state = GCST_OFFLINE;
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
// log counters
|
||||
GameClient_NetStats netstats;
|
||||
counters.calcNowStats( &netstats );
|
||||
log_error_np( LOG_OK, "=============================================\n" );
|
||||
log_error_np( LOG_OK, "Network usage stats:\n" );
|
||||
log_error_np( LOG_OK, "Bytes, packets sent: %I64u, %I64u\n", counters.ullBytesSent, counters.ullPacketsSent );
|
||||
log_error_np( LOG_OK, "Bytes, packets rcvd: %I64u, %I64u\n", counters.ullBytesRcvd, counters.ullPacketsRcvd );
|
||||
log_error_np( LOG_OK, "Time connected: %0.2f seconds\n", netstats.timePassedSecs );
|
||||
log_error_np( LOG_OK, "Avg send speed: %0.2f bytes/sec\n", netstats.avgSendSpeed );
|
||||
log_error_np( LOG_OK, "Avg recv speed: %0.2f bytes/sec\n", netstats.avgRecvSpeed );
|
||||
log_error_np( LOG_OK, "Avg send L2 packets: %0.2f packets/sec\n", netstats.avgSendPacketsPerSec );
|
||||
log_error_np( LOG_OK, "Avg recv L2 packets: %0.2f packets/sec\n", netstats.avgRecvPacketsPerSec );
|
||||
log_error_np( LOG_OK, "Avg out packet size: %0.2f bytes\n", netstats.avgSendPacketSize );
|
||||
log_error_np( LOG_OK, "Avg in packet size: %0.2f bytes\n", netstats.avgRecvPacketSize );
|
||||
log_error_np( LOG_OK, "=============================================\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
|
||||
//
|
||||
log_error( LOG_DEBUG, "GameClient::PC_sniff() ending, returning %d\n", (int)retVal );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
333
l2detect/GameClient_sniff_PP_client.cpp
Normal file
333
l2detect/GameClient_sniff_PP_client.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "L2PacketTypes.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
void GameClient::PP_sniff_fromClient( unsigned char *bytes, unsigned int len )
|
||||
{
|
||||
//int i = 0;
|
||||
if( !bytes || len<1 ) return;
|
||||
if( len<3 )
|
||||
{
|
||||
log_error( LOG_WARNING, "PP_sniff_fromClient(): packet len < 3!\n" );
|
||||
log_error( LOG_WARNING, "PP_sniff_fromClient(): bytes=0x%p, len=%d\n", bytes, len );
|
||||
return;
|
||||
}
|
||||
|
||||
// should we decrypt it?
|
||||
if( this->xor_enabled ) // yeah :)
|
||||
{
|
||||
if( !L2GamePacket::decodeXOR_buffer( bytes, len, this->key_client_cs ) )
|
||||
log_error( LOG_ERROR, "PP_sniff_fromClient(): decodeXOR_buffer() failed!\n" );
|
||||
}
|
||||
|
||||
// some vars
|
||||
unsigned char ptype = bytes[2];
|
||||
unsigned short int ptype2 = 0x0000;
|
||||
unsigned short int ptype3 = 0x0000;
|
||||
if( len >= 5 )
|
||||
{
|
||||
ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
}
|
||||
if( len >= 7 )
|
||||
{
|
||||
ptype3 |= (unsigned short int)(bytes[5] & 0xFFFF);
|
||||
ptype3 |= (unsigned short int)(bytes[6] << 8 & 0xFFFF);
|
||||
}
|
||||
|
||||
// obfuscator
|
||||
class L2PCodeObfuscator *lpco;
|
||||
lpco = (class L2PCodeObfuscator *)this->clsObfuscator;
|
||||
|
||||
if( lpco )
|
||||
{
|
||||
if( lpco->isEnabled() )
|
||||
{
|
||||
unsigned char pcode_prev = ptype;
|
||||
unsigned short pcode2_prev = ptype2;
|
||||
bool decode_res = lpco->decodeOpcode( ptype, ptype2, ptype3 );
|
||||
if( decode_res )
|
||||
{
|
||||
if( pcode2_prev == ptype2 )
|
||||
log_error( LOG_PACKETNAME, " **** de-obfuscated %02X -> %02X\n", pcode_prev, ptype );
|
||||
else
|
||||
log_error( LOG_PACKETNAME, " **** de-obfuscated %02X:%02X -> %02X:%02X\n",
|
||||
pcode_prev, pcode2_prev, ptype, ptype2 );
|
||||
}
|
||||
else
|
||||
log_error( LOG_ERROR, "PP_sniff_fromClient(): ERROR de-obfuscating %02X\n", pcode_prev );
|
||||
}
|
||||
}
|
||||
|
||||
L2PacketTypes_LogClient( (L2_VERSION)g_cfg.L2_client_version, this->state, ptype, ptype2, ptype3 );
|
||||
|
||||
// from client
|
||||
switch( this->state )
|
||||
{
|
||||
case GCST_CONNECTED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // ProtocolVersion // Interlude
|
||||
case 0x0e: // ProtocolVersion // Hellbound
|
||||
{
|
||||
L2Game_ProtocolVersion *p = new L2Game_ProtocolVersion( bytes, len );
|
||||
p->read_protoVer( &(this->gameProtoVer) );
|
||||
delete p;
|
||||
log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion %u\n", this->gameProtoVer );
|
||||
// client sends protocolVersion = 0xFFFFFFFF when it pings server (not tries to connect really)
|
||||
if( this->gameProtoVer >= 0xFFFFFFF0 )
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Received client ping server... no process\n" );
|
||||
this->thisWasJustServerPing = true; // received client ping (sniff)
|
||||
}
|
||||
} break; // ProtocolVersion
|
||||
// case 0x08: // AuthLogin // Interlude
|
||||
case 0x2b: // AuthLogin // Hellbound
|
||||
{
|
||||
L2Game_AuthLogin *p = new L2Game_AuthLogin( bytes, len );
|
||||
char login[32] = {0};
|
||||
p->read_login( login );
|
||||
delete p;
|
||||
log_error( LOG_PACKETNAME, "Client: 2b AuthLogin: Login: \"%s\"\n", login );
|
||||
} break; // AuthLogin
|
||||
default:
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "Client: Unknown packet %02X in state: CONNECTED\n",
|
||||
(unsigned int)ptype );
|
||||
if( g_cfg.DumpUnknownToStdout )
|
||||
{
|
||||
printf( "============================================\n" );
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
p->dumpToFile( stdout );
|
||||
delete p;
|
||||
printf( "============================================\n" );
|
||||
}
|
||||
} break;
|
||||
} // switch( ptype )
|
||||
} break; // CONNECTED
|
||||
|
||||
|
||||
case GCST_AUTHED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // LogoutRequest
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 00 LogoutRequest\n" );
|
||||
// } break;
|
||||
case 0x12: // CharacterSelect // Hellbound
|
||||
{
|
||||
int charSlot = bytes[3];
|
||||
//L2Game_CharacterSelect *p = new L2Game_CharacterSelect( bytes, len );
|
||||
log_error( LOG_PACKETNAME, "Client: 12 CharacterSelect: #%d\n", charSlot );
|
||||
//this->state = GCST_IN_GAME;
|
||||
//log_error( LOG_DEBUG, "Client: 12 CharacterSelect: switch state to IN_GAME\n" );
|
||||
} break; // CharacterSelect
|
||||
//case 0x13: // NewCharacter
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 13 NewCharacter\n" );
|
||||
// } break; // NewCharacter
|
||||
//case 0x0c: // CharacterCreate
|
||||
// {
|
||||
// wchar_t charNameU[64] = {0};
|
||||
// char charName[64] = {0};
|
||||
// wcscpy( charNameU, (const wchar_t *)(bytes+3) );
|
||||
// sprintf( charName, "%S", charNameU );
|
||||
// log_error( LOG_PACKETNAME, "Client: 0c CharacterCreate [%s]\n", charName );
|
||||
// } break; // CharacterCreate
|
||||
case 0xd0:
|
||||
{
|
||||
ptype2 = 0x0000;
|
||||
if( len >= 5 )
|
||||
{
|
||||
ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
if( ptype2 == 0x0039 )
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Client: d0:0039 RequestGotoLobby\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_WARNING, "Client: Unknown opcode2 %04X for state AUTHED packet 0xD0\n",
|
||||
(unsigned int)ptype2 );
|
||||
}
|
||||
}
|
||||
else
|
||||
log_error( LOG_WARNING, "Client: (AUTHED) sent 0xd0 without second opcode!\n" );
|
||||
} break; // double opcode packet
|
||||
default:
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Client: Unknown packet %02X in state: AUTHED\n",
|
||||
(unsigned int)ptype );
|
||||
if( g_cfg.DumpUnknownToStdout )
|
||||
{
|
||||
printf( "============================================\n" );
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
p->dumpToFile( stdout );
|
||||
delete p;
|
||||
printf( "============================================\n" );
|
||||
}
|
||||
} break;
|
||||
} // switch( ptype )
|
||||
} break; // AUTHED
|
||||
|
||||
|
||||
case GCST_IN_GAME:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // LogoutRequest
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 00 LogoutRequest\n" );
|
||||
// } break;
|
||||
//case 0x0f: // MoveBackwardToLocation
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 0f MoveBackwardToLocation\n" );
|
||||
// } break;
|
||||
//case 0x11: // EnterWorld
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 11 EnterWorld\n" );
|
||||
// } break;
|
||||
//case 0x14: // RequestItemList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 14 RequestItemList\n" );
|
||||
// } break;
|
||||
//case 0x19: // UseItem
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 19 UseItem\n" );
|
||||
// } break;
|
||||
case 0x1F: // Action
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Client: 1F Action\n" );
|
||||
L2Game_Action *p = new L2Game_Action( bytes, len );
|
||||
unsigned int oid = p->read_objectID();
|
||||
p->read_originX();
|
||||
p->read_originY();
|
||||
p->read_originZ();
|
||||
char useShift = p->read_useShift();
|
||||
delete p;
|
||||
if( useShift /* && g_cfg.altGameViewNpc */ )
|
||||
{
|
||||
L2OBJECT_TYPE objType = L2OT_NONE;
|
||||
int index = -1;
|
||||
if( WorldObjectTree_GetInfoByObjectID( oid, &objType, &index ) )
|
||||
{
|
||||
if( objType == L2OT_NPC )
|
||||
{
|
||||
L2Npc *npc = npc_array[index];
|
||||
char filename[256];
|
||||
sprintf( filename, "npc_%d_stats.txt", npc->templateID );
|
||||
FILE *f = fopen( filename, "wt" );
|
||||
fprintf( f, "x,y,z,heading: (%d,%d,%d) %u\n", npc->x, npc->y, npc->z, npc->heading );
|
||||
fprintf( f, "mAtkSpd, pAtkSpd: %d, %d\n", npc->mAtkSpd, npc->pAtkSpd );
|
||||
fprintf( f, "runSpeed, walkSpeed: %d, %d\n", npc->runSpeed, npc->walkSpeed );
|
||||
fprintf( f, "colR, colH: %0.2f, %0.2f\n", npc->collisionRadius, npc->collisionHeight );
|
||||
fprintf( f, "rhand, chest, lhand: %u, %u, %u\n", npc->iid_right_hand, npc->iid_chest, npc->iid_left_hand );
|
||||
fclose( f );
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
//case 0x23: // RequestBypassToServer
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 23 RequestBypassToServer\n" );
|
||||
// } break;
|
||||
//case 0x39: // RequestMagicSkillUse
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 39 RequestMagicSkillUse\n" );
|
||||
// } break;
|
||||
//case 0x3d: // RequestMagicSkillUse
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 3D RequestShortCutReg\n" );
|
||||
// } break;
|
||||
//case 0x48: // RequestTargetCanceld
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 48 RequestTargetCanceld\n" );
|
||||
// } break;
|
||||
//case 0x57: // RequestRestart
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 57 RequestRestart\n" );
|
||||
// //this->state = GCST_AUTHED;
|
||||
// } break;
|
||||
//case 0x59: // ValidatePosition
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 59 ValidatePosition\n" );
|
||||
// } break;
|
||||
//case 0x65: // RequestPledgeInfo
|
||||
// {
|
||||
// // TODO: parse RequestPledgeInfo?
|
||||
// log_error( LOG_PACKETNAME, "Client: 65 RequestPledgeInfo\n" );
|
||||
// } break;
|
||||
//case 0x8B: // RequestGmList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: 8B RequestGmList\n" );
|
||||
// } break;
|
||||
//case 0xA6: // RequestSkillCoolTime
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: A6 RequestSkillCoolTime\n" );
|
||||
// } break;
|
||||
//case 0xCB: // GameGuardReply
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: CB GameGuardReply\n" );
|
||||
// } break;
|
||||
//case 0xd0:
|
||||
// {
|
||||
// ptype2 = 0x00;
|
||||
// if( len >= 5 )
|
||||
// {
|
||||
// ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
// ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
// if( ptype2 == 0x01 )
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: D0:01 RequestManorList\n" );
|
||||
// }
|
||||
// else if( ptype2 == 0x0d )
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: D0:0D RequestAutoSoulShot\n" );
|
||||
// }
|
||||
// else if( ptype2 == 0x17 )
|
||||
// {
|
||||
// // TODO: RequestPledgeWarList
|
||||
// log_error( LOG_PACKETNAME, "Client: D0:17 RequestPledgeWarList\n" );
|
||||
// }
|
||||
// else if( ptype2 == 0x21 )
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: D0:21 RequestKeyMapping\n" );
|
||||
// }
|
||||
// else if( ptype2 == 0x24 )
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Client: D0:24 RequestSaveInventoryOrder\n" );
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log_error( LOG_WARNING, "Client: Unknown opcode2 %04X for IN_GAME packet 0xD0\n",
|
||||
// (unsigned int)ptype2 );
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// log_error( LOG_WARNING, "Client: (IN_GAME) sent 0xD0 without second opcode!\n" );
|
||||
// } break; // double opcode packet
|
||||
default:
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Client: Unknown packet %02X in state: IN_GAME\n",
|
||||
(unsigned int)ptype );
|
||||
if( g_cfg.DumpUnknownToStdout )
|
||||
{
|
||||
printf( "============================================\n" );
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
p->dumpToFile( stdout );
|
||||
delete p;
|
||||
printf( "============================================\n" );
|
||||
}
|
||||
} break;
|
||||
} // switch( ptype )
|
||||
} break; // IN_GAME
|
||||
|
||||
} // switch( state )
|
||||
}
|
||||
589
l2detect/GameClient_sniff_PP_server.cpp
Normal file
589
l2detect/GameClient_sniff_PP_server.cpp
Normal file
@@ -0,0 +1,589 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "CharArray.h"
|
||||
#include "ClanList.h"
|
||||
#include "L2PacketTypes.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
void GameClient::PP_sniff_fromServer( unsigned char *bytes, unsigned int len )
|
||||
{
|
||||
int i = 0;
|
||||
if( !bytes || len<1 ) return;
|
||||
if( len<3 )
|
||||
{
|
||||
log_error( LOG_WARNING, "PP_sniff_fromServer(): packet len < 3!\n" );
|
||||
log_error( LOG_WARNING, "PP_sniff_fromServer(): bytes=0x%p, len=%d\n", bytes, len );
|
||||
return;
|
||||
}
|
||||
|
||||
// should we decrypt it?
|
||||
if( this->xor_enabled ) // yeah :)
|
||||
{
|
||||
if( !L2GamePacket::decodeXOR_buffer( bytes, len, this->key_client_sc ) )
|
||||
log_error( LOG_ERROR, "PP_sniff_fromServer(): decodeXOR_buffer() failed!\n" );
|
||||
}
|
||||
|
||||
// some vars
|
||||
unsigned char ptype = bytes[2];
|
||||
unsigned short int ptype2 = 0x0000;
|
||||
unsigned short int ptype3 = 0x0000;
|
||||
if( len >= 5 )
|
||||
{
|
||||
ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
}
|
||||
if( len >= 7 )
|
||||
{
|
||||
ptype3 |= (unsigned short int)(bytes[5] & 0xFFFF);
|
||||
ptype3 |= (unsigned short int)(bytes[6] << 8 & 0xFFFF);
|
||||
}
|
||||
|
||||
// obfuscator
|
||||
class L2PCodeObfuscator *lpco;
|
||||
lpco = (class L2PCodeObfuscator *)this->clsObfuscator;
|
||||
|
||||
if( lpco )
|
||||
{
|
||||
if( lpco->isEnabled() && (g_cfg.L2_version != (int)L2_VERSION_T23) )
|
||||
{
|
||||
unsigned char pcode_prev = ptype;
|
||||
unsigned short pcode2_prev = ptype2;
|
||||
bool decode_res = lpco->decodeOpcode( ptype, ptype2, ptype3 );
|
||||
if( decode_res )
|
||||
{
|
||||
if( pcode2_prev == ptype2 )
|
||||
log_error( LOG_PACKETNAME, "PP_sniff_fromServer(): de-obfuscated %02X -> %02X\n", pcode_prev, ptype );
|
||||
else
|
||||
log_error( LOG_PACKETNAME, "PP_sniff_fromServer(): de-obfuscated %02X:%02X -> %02X:%02X\n",
|
||||
pcode_prev, pcode2_prev, ptype, ptype2 );
|
||||
}
|
||||
else
|
||||
log_error( LOG_ERROR, "PP_snigg_fromServer(): ERROR de-obfuscating %02X\n", pcode_prev, ptype );
|
||||
}
|
||||
}
|
||||
|
||||
L2PacketTypes_LogServer( (L2_VERSION)g_cfg.L2_version, this->state, ptype, ptype2, ptype3 );
|
||||
|
||||
switch( this->state )
|
||||
{
|
||||
case GCST_CONNECTED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // Interlude: KeyPacket, FirstKey
|
||||
case 0x2e: // Hellbound: KeyPacket, FirstKey
|
||||
{
|
||||
L2Game_KeyPacket *p = new L2Game_KeyPacket( bytes, len );
|
||||
p->read_key( this->key_client_cs );
|
||||
p->read_GameServerID();
|
||||
this->opcodeObfuscator = p->read_OpcodeObfuscator();
|
||||
L2Game_KeyPacket::createInitialHellboundKey( this->key_client_cs,
|
||||
this->key_client_cs );
|
||||
delete p;
|
||||
memcpy( this->key_client_sc, this->key_client_cs,
|
||||
sizeof(this->key_client_cs) );
|
||||
this->xor_enabled = true;
|
||||
log_error( LOG_PACKETNAME, "Server: 2e KeyPacket\n" );
|
||||
log_error( LOG_DEBUGDUMP, "Server: 2e KeyPacket: key: " );
|
||||
for( i=0; i<16; i++ ) log_error_np( LOG_DEBUGDUMP, "%02X ", this->key_client_cs[i] );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
// log obfuscator, if it is != 0x00000000
|
||||
LOG_LEVEL log_level = LOG_DEBUGDUMP;
|
||||
if( this->opcodeObfuscator != 0x00000000 )
|
||||
{
|
||||
log_level = LOG_WARNING;
|
||||
log_error( log_level, "Server: 2e KeyPacket: Obfuscator: 0x%04X\n", this->opcodeObfuscator );
|
||||
// delete obfuscator, if exists
|
||||
if( lpco )
|
||||
{
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
lpco = new L2PCodeObfuscator();
|
||||
//lpco->setVersionMode_T22();
|
||||
// TODO: Obfuscator set L2 Version
|
||||
lpco->setVersionMode( (L2_VERSION)g_cfg.L2_version );
|
||||
lpco->init_tables( this->opcodeObfuscator );
|
||||
this->clsObfuscator = (void *)lpco;
|
||||
}
|
||||
} break; // KeyPacket
|
||||
case 0x09: // CharacterSelectionInfo // Hellbound
|
||||
{
|
||||
int nChars = bytes[3];
|
||||
log_error( LOG_PACKETNAME, "Server: 09 CharacterSelectionInfo: %d chars\n", nChars );
|
||||
this->state = GCST_AUTHED;
|
||||
log_error( LOG_DEBUG, "Server: 09 CharacterSelectionInfo: switch state to AUTHED\n" );
|
||||
} break; // CharacterSelectionInfo
|
||||
default:
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Server: Unknown packet %02X in state: CONNECTED\n",
|
||||
(unsigned int)ptype );
|
||||
if( g_cfg.DumpUnknownToStdout )
|
||||
{
|
||||
printf( "============================================\n" );
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
p->dumpToFile( stdout );
|
||||
delete p;
|
||||
printf( "============================================\n" );
|
||||
}
|
||||
} break;
|
||||
} // switch( ptype )
|
||||
} break; // GCST_CONNECTED
|
||||
|
||||
|
||||
case GCST_AUTHED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
case 0x09: // CharacterSelectionInfo // Hellbound
|
||||
{
|
||||
int nChars = bytes[3];
|
||||
log_error( LOG_PACKETNAME, "Server: 09 CharacterSelectionInfo: %d chars\n", nChars );
|
||||
} break; // CharacterSelectionInfo
|
||||
case 0x0b: // CharSelected
|
||||
{
|
||||
// TODO: CharSelected parse, get clan ID
|
||||
wchar_t char_name[128] = {0};
|
||||
wcscpy( char_name, (const wchar_t *)(bytes+3) );
|
||||
log_error( LOG_PACKETNAME, "Server: 0b CharSelected: \"%S\"\n", char_name );
|
||||
this->state = GCST_IN_GAME;
|
||||
log_error( LOG_DEBUG, "Server: 0b CharSelected: switch state from AUTHED to IN_GAME\n" );
|
||||
this->opcodeObfuscator = 0;
|
||||
this->opcodeObfuscator = bytes[len-4] | (bytes[len-3] << 8) | (bytes[len-2] << 16) | (bytes[len-1] << 24);
|
||||
if( this->opcodeObfuscator != 0x00000000 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Opcode obfuscation is enabled in CharSelected packet, 0x%08X\n",
|
||||
this->opcodeObfuscator );
|
||||
// delete obfuscator, if exists
|
||||
if( lpco )
|
||||
{
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
lpco = new L2PCodeObfuscator();
|
||||
//lpco->setVersionMode_T22();
|
||||
// TODO: Obfuscator set L2 Version
|
||||
lpco->setVersionMode( (L2_VERSION)g_cfg.L2_version );
|
||||
lpco->init_tables( this->opcodeObfuscator );
|
||||
this->clsObfuscator = (void *)lpco;
|
||||
}
|
||||
} break;
|
||||
//case 0x0d: // NewCharacterSuccess
|
||||
// {
|
||||
// int nTemplates = bytes[3];
|
||||
// log_error( LOG_PACKETNAME, "Server: 0d NewCharacterSuccess; char_templates: %d\n",
|
||||
// nTemplates );
|
||||
// } break; // NewCharacterSuccess
|
||||
//case 0x0f: // CharCreateOK
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 0f CharCreateOK\n" );
|
||||
// } break; // CharCreateOK
|
||||
case 0x73: // SSQInfo // Hellbound
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 73 SSQInfo\n" );
|
||||
this->state = GCST_IN_GAME;
|
||||
log_error( LOG_PACKETNAME, "Server: 73 SSQInfo, switch state to IN_GAME\n" );
|
||||
} break; // SSQInfo
|
||||
default:
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "Server: Unknown packet %02X in state: AUTHED\n",
|
||||
(unsigned int)ptype );
|
||||
if( g_cfg.DumpUnknownToStdout )
|
||||
{
|
||||
printf( "============================================\n" );
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
p->dumpToFile( stdout );
|
||||
delete p;
|
||||
printf( "============================================\n" );
|
||||
}
|
||||
} break;
|
||||
} // switch( ptype )
|
||||
} break; // GCST_AUTHED
|
||||
|
||||
|
||||
case GCST_IN_GAME:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
//case 0x00: // Die
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 00 Die\n" );
|
||||
// } break; // Die
|
||||
//case 0x05: // SpawnItem
|
||||
// {
|
||||
// TODO: SpawnItem parse
|
||||
/* protected final void writeImpl()
|
||||
{
|
||||
writeC(0x05);
|
||||
writeD(_objectId);
|
||||
writeD(_itemId);
|
||||
|
||||
writeD(_x);
|
||||
writeD(_y);
|
||||
writeD(_z);
|
||||
// only show item count if it is a stackable item
|
||||
writeD(_stackable);
|
||||
writeD(_count);
|
||||
writeD(0x00); //c2
|
||||
}*/
|
||||
// log_error( LOG_PACKETNAME, "Server: 05 SpawnItem\n" );
|
||||
// } break; // SpawnItem
|
||||
case 0x08: // DeleteObject
|
||||
{
|
||||
// TODO: parse DeleteObject
|
||||
// [3,4,5,6] - objectId
|
||||
//unsigned int oid = bytes[3] | (bytes[4] << 8) | (bytes[5] << 16) | (bytes[6] << 24);
|
||||
//log_error( LOG_PACKETNAME, "Server: 08 DeleteObject %u\n", oid );
|
||||
//CharArray_DeleteCharByObjectID( oid );
|
||||
ai.notifyEventPacket( UAI_PEVENT_DELETEOBJECT, bytes, len );
|
||||
} break; // DeleteObject
|
||||
case 0x0b: // CharSelected
|
||||
{
|
||||
// TODO: CharSelected parse, get clan ID
|
||||
wchar_t char_name[128] = {0};
|
||||
wcscpy( char_name, (const wchar_t *)(bytes+3) );
|
||||
log_error( LOG_PACKETNAME, "Server: 0b CharSelected: \"%S\"\n", char_name );
|
||||
this->state = GCST_IN_GAME;
|
||||
log_error( LOG_DEBUG, "Server: 0b CharSelected: switch state from IN_GAME to IN_GAME\n" );
|
||||
this->opcodeObfuscator = bytes[len-4] | (bytes[len-3] << 8) | (bytes[len-2] << 16) | (bytes[len-1] << 24);
|
||||
if( this->opcodeObfuscator != 0x00000000 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Opcode obfuscation is enabled in CharSelected packet, 0x%08X\n",
|
||||
this->opcodeObfuscator );
|
||||
// delete obfuscator, if exists
|
||||
if( lpco )
|
||||
{
|
||||
lpco->clear();
|
||||
delete lpco;
|
||||
this->clsObfuscator = NULL;
|
||||
}
|
||||
lpco = new L2PCodeObfuscator();
|
||||
//lpco->setVersionMode_T22();
|
||||
// TODO: Obfuscator set L2 Version
|
||||
lpco->setVersionMode( (L2_VERSION)g_cfg.L2_version );
|
||||
lpco->init_tables( this->opcodeObfuscator );
|
||||
this->clsObfuscator = (void *)lpco;
|
||||
}
|
||||
} break;
|
||||
case 0x0c: // NpcInfo (mob)?
|
||||
{
|
||||
/*unsigned int idTemplate = 0;
|
||||
unsigned char *p = (unsigned char *)&idTemplate;
|
||||
// bytes[2] is ptype(0x0c); objectID[3,4,5,6]; idTemplate[7,8,9,10]....
|
||||
p[0] = bytes[7];
|
||||
p[1] = bytes[8];
|
||||
p[2] = bytes[9];
|
||||
p[3] = bytes[10];
|
||||
idTemplate -= 1000000; // ? :) L2J adds 1000000 to this field
|
||||
// c,18d,4f,3d,5c,name,title!
|
||||
int name_offset = 3 + 18*sizeof(int) + 4*sizeof(double) + 3*sizeof(int) + 5;
|
||||
wchar_t name[128];
|
||||
memset( name, 0, sizeof(name) );
|
||||
wcsncpy( name, (const wchar_t *)(bytes+name_offset), 127 );
|
||||
name[127] = 0;
|
||||
log_error( LOG_PACKETNAME, "Server: 0c NpcInfo (mob/morphed char?): id_%u, [%S]\n",
|
||||
idTemplate, name );*/
|
||||
ai.notifyEventPacket( UAI_PEVENT_NPCINFO, bytes, len );
|
||||
} break;
|
||||
case 0x11: // ItemList
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 11 ItemList\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_ITEMLIST, bytes, len );
|
||||
} break; // ItemList
|
||||
case 0x18: // StatusUpdate
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 18 StatusUpdate\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_STATUSUPDATE, bytes, len );
|
||||
} break; // StatusUpdate
|
||||
//case 0x19: // NpcHtmlMessage
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 19 NpcHtmlMessage\n" );
|
||||
// } break; // NpcHtmlMessage
|
||||
//case 0x1F: // ActionFailed
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 1F ActionFailed\n" );
|
||||
// } break; // ActionFailed
|
||||
case 0x21: // InventoryUpdate
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 21 InventoryUpdate\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_INVENTORYUPDATE, bytes, len );
|
||||
} break; // InventoryUpdate
|
||||
case 0x23: // TargetSelected
|
||||
{
|
||||
// TODO: TargetSelected
|
||||
/* writeC(0x23);
|
||||
writeD(_objectId);
|
||||
writeD(_targetObjId);
|
||||
writeD(_x);
|
||||
writeD(_y);
|
||||
writeD(_z);
|
||||
writeD(0x00); */
|
||||
// bytes[0], bytes[1] - packet size; bytes[3] - pcode
|
||||
unsigned int objectID = bytes[3] | (bytes[4] << 8) | (bytes[5] << 16) | (bytes[6] <<24);
|
||||
unsigned int targetObjID = bytes[7] | (bytes[8] << 8) | (bytes[9] << 16) | (bytes[10] <<24);
|
||||
log_error( LOG_PACKETNAME, "Server: 23 TargetSelected [%u] -> [%u]\n",
|
||||
objectID, targetObjID );
|
||||
ai.notifyEventPacket( UAI_PEVENT_TARGETSELECTED, bytes, len );
|
||||
} break; // TargetSelected
|
||||
case 0x24: // TargetUnselected
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 24 TargetUnselected\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_TARGETUNSELECTED, bytes, len );
|
||||
} break; // TargetUnselected
|
||||
//case 0x25: // AutoAttackStart
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 25 AutoAttackStart\n" );
|
||||
// } break; // AutoAttackStart
|
||||
//case 0x26: // AutoAttackStop
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 26 AutoAttackStop\n" );
|
||||
// } break; // AutoAttackStop
|
||||
//case 0x27: // SocialAction
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 27 SocialAction\n" );
|
||||
// } break; // SocialAction
|
||||
//case 0x28: // ChangeMoveType
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 28 ChangeMoveType\n" );
|
||||
// } break; // ChangeMoveType
|
||||
case 0x2f: // MoveToLocation
|
||||
{
|
||||
//
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
unsigned int oid = p->readUInt();
|
||||
delete p;
|
||||
int itsme = (int)( oid == ai.usr.objectID );
|
||||
//
|
||||
log_error( LOG_PACKETNAME, "Server: 2f MoveToLocation [%u] (my oid %u; its me: %d)\n",
|
||||
oid, ai.usr.objectID, itsme );
|
||||
ai.notifyEventPacket( UAI_PEVENT_MOVETOLOCATION, bytes, len );
|
||||
} break; // MoveToLocation
|
||||
case 0x31: // CharInfo
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 31 CharInfo\n" );
|
||||
//CharList_Add( name, title, oid, x,y,z, heading, race, sex, baseClass, clanID );
|
||||
ai.notifyEventPacket( UAI_PEVENT_CHARINFO, bytes, len );
|
||||
} break; // NpcInfo
|
||||
case 0x32: // UserInfo
|
||||
{
|
||||
//
|
||||
ai.notifyEventPacket( UAI_PEVENT_USERINFO, bytes, len );
|
||||
} break; // UserInfo
|
||||
//case 0x44: // ShortCutRegister
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 44 ShortCutRegister\n" );
|
||||
// } break; // ShortCutRegister
|
||||
//case 0x45: // ShortCutInit
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 45 ShortCutInit\n" );
|
||||
// } break; // ShortCutInit
|
||||
//case 0x47: // StopMove
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 47 StopMove\n" );
|
||||
// } break; // StopMove
|
||||
//case 0x48: // MagicSkillUse
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 48 MagicSkillUse\n" );
|
||||
// } break; // MagicSkillUse
|
||||
//case 0x4A: // CreatureSay
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 4A CreatureSay\n" );
|
||||
// // TODO: CreatureSay parse
|
||||
// } break; // CreatureSay
|
||||
//case 0x54: // MagicSkillLaunched
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 54 MagicSkillLaunched\n" );
|
||||
// } break; // MagicSkillLaunched
|
||||
//case 0x5A: // PledgeShowMemberListAll
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5A PledgeShowMemberListAll\n" );
|
||||
// } break; // PledgeShowMemberListAll
|
||||
//case 0x5B: // PledgeShowMemberListUpdate
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5B PledgeShowMemberListUpdate\n" );
|
||||
// } break; // PledgeShowMemberListUpdate
|
||||
//case 0x5C: // PledgeShowMemberListAdd
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5C PledgeShowMemberListAdd\n" );
|
||||
// } break; // PledgeShowMemberListAdd
|
||||
//case 0x5F: // SkillList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 5F SkillList\n" );
|
||||
// } break; // SkillList
|
||||
//case 0x62: // SystemMessage
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 62 SystemMessage\n" );
|
||||
// } break; // SystemMessage
|
||||
//case 0x6b: // SetupGauge
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 6B SetupGauge\n" );
|
||||
// } break; // SetupGauge
|
||||
//case 0x72: // MoveToPawn
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 72 MoveToPawn\n" );
|
||||
// } break; // MoveToPawn
|
||||
case 0x71: // RestartResponse (RestartOK)
|
||||
{
|
||||
// notify user AI that user is not in game
|
||||
ai.userLogout();
|
||||
log_error( LOG_PACKETNAME, "Server: 71 RestartResponse (RestartOK)\n" );
|
||||
this->state = GCST_AUTHED;
|
||||
log_error( LOG_DEBUG, "Server: 71 RestartResponse: switch state to AUTHED\n" );
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
} break; // RestartResponse
|
||||
//case 0x74: // GameGuardQuery
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 74 GameGuardQuery\n" );
|
||||
// } break; // GameGuardQuery
|
||||
//case 0x79: // ValidateLocation
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 79 ValidateLocation\n" );
|
||||
// } break; // ValidateLocation
|
||||
//case 0x7B: // ShowBoard
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 7B ShowBoard\n" );
|
||||
// } break; // ShowBoard
|
||||
case 0x84: // LeaveWorld
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: 84 LeaveWorld\n" );
|
||||
ai.userLogout();
|
||||
} break; // LeaveWorld
|
||||
//case 0x85: // AbnormalStatusUpdate
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 85 AbnormalStatusUpdate\n" );
|
||||
// } break; // AbnormalStatusUpdate
|
||||
//case 0x86: // QuestList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 86 QuestList\n" );
|
||||
// } break; // QuestList
|
||||
case 0x89: // PledgeInfo
|
||||
{
|
||||
// TODO: parse PledgeInfo
|
||||
// writeC(0x89);
|
||||
// writeD(_clan.getClanId());
|
||||
// writeS(_clan.getName());
|
||||
// writeS(_clan.getAllyName());
|
||||
unsigned int clanID = bytes[3] | (bytes[4] << 8) | (bytes[5] << 16) | (bytes[6] << 24);
|
||||
wchar_t clan_name[128] = {0};
|
||||
wchar_t ally_name[128] = {0};
|
||||
unsigned int offset = 7; // 2(plen) + 1(pcode) + 4(clanID);
|
||||
wcscpy( clan_name, (const wchar_t *)(bytes + offset) );
|
||||
offset += wcslen( clan_name ) * 2 + 2; // now we can read ally_name from offset
|
||||
wcscpy( ally_name, (const wchar_t *)(bytes + offset) );
|
||||
ClanList_Add( clanID, clan_name, ally_name );
|
||||
log_error( LOG_PACKETNAME, "Server: 89 PledgeInfo %u [%S] Ally: [%S]\n",
|
||||
clanID, clan_name, ally_name );
|
||||
} break; // PledgeInfo
|
||||
//case 0x9F: // StaticObject
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: 9F StaticObject\n" );
|
||||
// } break; // StaticObject
|
||||
//case 0xB9: // MyTargetSelected
|
||||
// {
|
||||
// unsigned int objectID = bytes[3] | (bytes[4] << 8) | (bytes[5] << 16) | (bytes[6] <<24);
|
||||
// log_error( LOG_PACKETNAME, "Server: B9 MyTargetSelected [%u]\n", objectID );
|
||||
// } break; // MyTargetSelected
|
||||
//case 0xC7: // SkillCoolTime
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: C7 SkillCoolTime\n" );
|
||||
// } break; // SkillCoolTime
|
||||
//case 0xCD: // PledgeStatusChanged
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: CD PledgeStatusChanged\n" );
|
||||
// } break; // PledgeStatusChanged
|
||||
case 0xCE: // RelationChanged
|
||||
{
|
||||
//log_error( LOG_PACKETNAME, "Server: CE RelationChanged\n" );
|
||||
ai.notifyEventPacket( UAI_PEVENT_RELATIONCHANGED, bytes, len );
|
||||
} break; // RelationChanged
|
||||
//case 0xE5: // HennaInfo
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: E5 HennaInfo\n" );
|
||||
// } break; // HennaInfo
|
||||
//case 0xE8: // SendMacroList
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: E8 SendMacroList\n" );
|
||||
// } break; // SendMacroList
|
||||
//case 0xF2: // ClientSetTime
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: F2 ClientSetTime\n" );
|
||||
// } break; // ClientSetTime
|
||||
//case 0xF9: // EtcStatusUpdate
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: F9 EtcStatusUpdate\n" );
|
||||
// } break; // EtcStatusUpdate
|
||||
//case 0xFD: // AgitDecoInfo
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FD AgitDecoInfo\n" );
|
||||
// } break; // AgitDecoInfo
|
||||
//case 0xFE: // double-byte packet
|
||||
// {
|
||||
// ptype2 = 0x00;
|
||||
// if( len >= 5 )
|
||||
// {
|
||||
// ptype2 |= (unsigned short int)(bytes[3] & 0xFFFF);
|
||||
// ptype2 |= (unsigned short int)(bytes[4] << 8 & 0xFFFF);
|
||||
// switch( ptype2 )
|
||||
// {
|
||||
// case 0x0c: // ExAutoSoulShot FE:0C
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:0C ExAutoSoulShot\n" );
|
||||
// } break;
|
||||
// case 0x22: // ExSendManorList FE:22
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:22 ExSendManorList\n" );
|
||||
// } break;
|
||||
// case 0x2f: // ExStorageMaxCount FE:2f
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:2F ExStorageMaxCount\n" );
|
||||
// } break;
|
||||
// case 0x33: // ExSetCompassZoneCode FE:33
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:33 ExSetCompassZoneCode\n" );
|
||||
// } break;
|
||||
// case 0x3a: // PledgeSkillList FE:3A
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:3A PledgeSkillList\n" );
|
||||
// } break;
|
||||
// case 0x3f: // PledgeReceiveWarList FE:3F
|
||||
// {
|
||||
// // TODO: PledgeReceiveWarList parse
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:3F PledgeReceiveWarList\n" );
|
||||
// } break;
|
||||
// case 0x40: // PledgeReceiveSubPledgeCreated FE:40
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:40 PledgeReceiveSubPledgeCreated\n" );
|
||||
// } break;
|
||||
// case 0x5f: // ExBasicActionList FE:5F
|
||||
// {
|
||||
// log_error( LOG_PACKETNAME, "Server: FE:5F ExBasicActionList\n" );
|
||||
// } break;
|
||||
// default: log_error( LOG_WARNING, "Server: Unknown opcode2 %04X for IN_GAME packet 0xFE\n",
|
||||
// (unsigned int)ptype2 ); break;
|
||||
// }
|
||||
// }
|
||||
// else log_error( LOG_WARNING, "Server: (IN_GAME) sent 0xFE without second opcode!\n" );
|
||||
// } break; // double-byte packet
|
||||
default:
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Server: Unknown packet %02X in state: IN_GAME\n",
|
||||
(unsigned int)ptype );
|
||||
if( g_cfg.DumpUnknownToStdout )
|
||||
{
|
||||
printf( "============================================\n" );
|
||||
L2GamePacket *p = new L2GamePacket( bytes, len );
|
||||
p->dumpToFile( stdout );
|
||||
delete p;
|
||||
printf( "============================================\n" );
|
||||
}
|
||||
} break;
|
||||
} // switch( ptype )
|
||||
} break; // GCST_IN_GAME
|
||||
} // switch( state )
|
||||
}
|
||||
383
l2detect/GameListener.cpp
Normal file
383
l2detect/GameListener.cpp
Normal file
@@ -0,0 +1,383 @@
|
||||
#include "stdafx.h"
|
||||
#include "GameListener.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "LoginListener.h"
|
||||
|
||||
extern class CConfig g_cfg; // in main.cpp
|
||||
extern class LoginListener *g_plogin; // in main.cpp
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
struct FLGT_INFO
|
||||
{
|
||||
class GameListener *cls;
|
||||
};
|
||||
|
||||
void FGS_Thread_freeInfo( struct FLGT_INFO *pinfo )
|
||||
{
|
||||
if( pinfo->cls->m_listen_socket != INVALID_SOCKET )
|
||||
{
|
||||
L2PNet_shutdown( pinfo->cls->m_listen_socket );
|
||||
L2PNet_closesocket( pinfo->cls->m_listen_socket );
|
||||
pinfo->cls->m_listen_socket = INVALID_SOCKET;
|
||||
}
|
||||
if( pinfo->cls->m_hThread ) CloseHandle( pinfo->cls->m_hThread );
|
||||
pinfo->cls->m_hThread = NULL;
|
||||
pinfo->cls->m_signal = 0;
|
||||
free( pinfo );
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): thread info struct freed\n" );
|
||||
}
|
||||
|
||||
DWORD WINAPI FGS_Thread( LPVOID lpParam )
|
||||
{
|
||||
struct FLGT_INFO *pinfo = (struct FLGT_INFO *)lpParam;
|
||||
lpParam = NULL;
|
||||
if( !pinfo )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): lpParam is NULL! Exit\n" );
|
||||
return 0;
|
||||
}
|
||||
class GameListener *cls = pinfo->cls;
|
||||
if( !cls )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): pinfo->cls is NULL! Exit\n" );
|
||||
FGS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
cls->m_signal = 0;
|
||||
cls->m_listen_socket = INVALID_SOCKET;
|
||||
|
||||
SOCKET s = L2PNet_TCPsocket_create( true );
|
||||
if( s == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): socket create failed!\n" );
|
||||
FGS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sbind_tries = 32;
|
||||
bool bind_OK = false;
|
||||
int FakeListenGamePort_prev = g_cfg.FakeListenGamePort;
|
||||
while( sbind_tries > 0 )
|
||||
{
|
||||
if( L2PNet_bind( s, g_cfg.FakeListenGameIP, (unsigned short)g_cfg.FakeListenGamePort ) )
|
||||
{
|
||||
g_cfg.FakeListenGamePort++;
|
||||
sbind_tries--;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
bind_OK = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !bind_OK )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): ERROR: all 32 attempts of socket binds failed\n" );
|
||||
FGS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): successfully bound GameListener to %s:%d\n",
|
||||
g_cfg.FakeListenGameIP, g_cfg.FakeListenGamePort );
|
||||
|
||||
if( L2PNet_listen( s ) )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): listen() failed\n" );
|
||||
FGS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
cls->m_listen_socket = s;
|
||||
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): started, listening at %s:%d\n",
|
||||
g_cfg.FakeListenGameIP, g_cfg.FakeListenGamePort );
|
||||
|
||||
// raise thread priority if enabled
|
||||
if( g_cfg.ThreadProirityRaiseEnable )
|
||||
{
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): raising thread priority\n" );
|
||||
if( !SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST ) )
|
||||
log_error( LOG_WARNING, "FGS_Thread(): raise thread priority failed!\n" );
|
||||
}
|
||||
|
||||
ErrorLogger_FlushLogFile();
|
||||
|
||||
bool processClient_result = false;
|
||||
int r = 0;
|
||||
char clientIP[32] = {0};
|
||||
unsigned short int clientPort = 0;
|
||||
SOCKET scl = INVALID_SOCKET;
|
||||
int should_exit = 0;
|
||||
unsigned int scode = 0; // signal to thread
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
r = L2PNet_select( s, L2PNET_SELECT_READ, 50, NULL, NULL );
|
||||
|
||||
should_exit = 0;
|
||||
scode = cls->getLastSignal();
|
||||
if( scode == FLGS_STOP )
|
||||
{
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): exit signal\n" );
|
||||
should_exit = 1;
|
||||
break;
|
||||
}
|
||||
if( should_exit == 1 ) break;
|
||||
|
||||
if( r == -1 )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): socket select() error\n" );
|
||||
break;
|
||||
}
|
||||
if( r == 1 )
|
||||
{
|
||||
//log_error( LOG_DEBUG, "FGS_Thread: Somebody connected? :)\n" );
|
||||
clientIP[0] = 0;
|
||||
clientPort = 0;
|
||||
scl = INVALID_SOCKET;
|
||||
scl = L2PNet_accept( s, clientIP, &clientPort );
|
||||
if( scl == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "FGS_Thread(): ERROR: accept failed...\n" );
|
||||
}
|
||||
else // Game client connected
|
||||
{
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): accepted client %s:%d\n",
|
||||
clientIP, clientPort );
|
||||
PlayServerInfo sinfo;
|
||||
memset( &sinfo, 0, sizeof(PlayServerInfo) );
|
||||
cls->getPlayServerInfo( &sinfo );
|
||||
should_exit = 0;
|
||||
while( (sinfo.ip[0] == 0) || (sinfo.port == 0 ) )
|
||||
{
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): PlayServerInfo is meaningless, "
|
||||
"waiting for setting correct values...\n" );
|
||||
sinfo.ip[0] = 0; sinfo.port = 0;
|
||||
Sleep( 300 ); // wait 300 msec while threads switch :)
|
||||
cls->getPlayServerInfo( &sinfo );
|
||||
// enable stopping game server listener from this loop
|
||||
should_exit = 0;
|
||||
scode = cls->getLastSignal();
|
||||
if( scode == FLGS_STOP )
|
||||
{
|
||||
log_error( LOG_DEBUG, "FGS_Thread: exit signal\n" );
|
||||
should_exit = 1;
|
||||
break; // break from first loop
|
||||
}
|
||||
}
|
||||
if( should_exit ) break; // break from next (upper) loop
|
||||
|
||||
// wait for LoginListener is stopped in outgame mode
|
||||
if( (g_cfg.isInGameMode == false) && g_plogin )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
DWORD tc = GetTickCount();
|
||||
log_error( LOG_DEBUG, "GameListener: waiting for LoginListener to stop in OOG mode...\n" );
|
||||
#endif
|
||||
g_plogin->waitStopped( 1000 );
|
||||
#ifdef _DEBUG
|
||||
DWORD tc_passed = GetTickCount() - tc;
|
||||
log_error( LOG_DEBUG, "GameListener: wait for LoginListener to stop in OOG mode ended in %u msec\n",
|
||||
tc_passed );
|
||||
#endif
|
||||
}
|
||||
|
||||
// initialize gameClient UserAI
|
||||
g_game_client->ai.init();
|
||||
|
||||
/* only sniffer mode? */
|
||||
if( g_cfg.EnableModifyGameTraffic == 0 )
|
||||
{
|
||||
//log_error( LOG_DEBUG, "FGS_Thread(): start ProcessClient, sniffing only\n" );
|
||||
log_error( LOG_OK, "GameListener: start processing client, sniffing only\n" );
|
||||
processClient_result = g_game_client->PC_sniff( scl, sinfo.ip, sinfo.port );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_DEBUG, "FGS_Thread(): start ProcessClient, full processing mode\n" );
|
||||
processClient_result = g_game_client->PC_full( scl, sinfo.ip, sinfo.port );
|
||||
} // if( g_cfg.EnableModifyGameTraffic == 0 )
|
||||
|
||||
// TODO: better error handling
|
||||
if( !processClient_result )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameListener: FGS_Thread(): ProcessClient_xxxx() returned false, network error?\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
|
||||
if( cls->getLastSignal() == FLGS_STOP ) break;
|
||||
|
||||
// run login listener again in outgame mode
|
||||
//if( processClient_result && (g_cfg.isInGameMode == false) )
|
||||
if( g_cfg.isInGameMode == false )
|
||||
{
|
||||
if( g_plogin )
|
||||
{
|
||||
if( !g_game_client->wasJustServerPing() )
|
||||
{
|
||||
log_error( LOG_DEBUG, "GameListener: starting LoginListener again in outgame mode\n" );
|
||||
if( !g_plogin->start() )
|
||||
log_error( LOG_ERROR, "GameListener: failed starting LoginListener again in outgame mode!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( g_plogin->isRunning() )
|
||||
{
|
||||
log_error( LOG_WARNING, "GameListener: GameClient ended, "
|
||||
"but it was just server ping - no start LoginListener!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_WARNING, "GameListener: GameClient ended after client->server ping, "
|
||||
"but LoginListener is not running...? O_o\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // accept() OK
|
||||
} // somebody connected?
|
||||
} // while(1)
|
||||
|
||||
// restore prev. listen game port that was set in config after client processing ended
|
||||
g_cfg.FakeListenGamePort = FakeListenGamePort_prev;
|
||||
|
||||
FGS_Thread_freeInfo( pinfo );
|
||||
log_error( LOG_DEBUG, "FGS_Thread() ended\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// class
|
||||
|
||||
|
||||
GameListener::GameListener()
|
||||
{
|
||||
this->_initNull();
|
||||
}
|
||||
|
||||
GameListener::~GameListener()
|
||||
{
|
||||
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
||||
this->_initNull();
|
||||
}
|
||||
|
||||
|
||||
bool GameListener::start()
|
||||
{
|
||||
// cleanup ?
|
||||
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
||||
this->_initNull();
|
||||
// alloc thread info struct
|
||||
struct FLGT_INFO *pinfo = (struct FLGT_INFO *)malloc( sizeof( struct FLGT_INFO ) );
|
||||
if( !pinfo ) return false;
|
||||
// fill info
|
||||
pinfo->cls = this;
|
||||
|
||||
// create thread object
|
||||
this->m_hThread = NULL;
|
||||
DWORD dwTID = 0;
|
||||
this->m_hThread = (HANDLE)_beginthreadex(
|
||||
NULL, // security
|
||||
0, // stack size
|
||||
(unsigned int (__stdcall*)(void *))FGS_Thread, // thread function
|
||||
(void *)pinfo, // thread function argument - lpParam
|
||||
0, // flags
|
||||
(unsigned int *)(&dwTID) );
|
||||
if( !this->m_hThread )
|
||||
{
|
||||
free( pinfo );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameListener::waitStopped( unsigned int timeoutMsec )
|
||||
{
|
||||
if( !this->m_hThread ) return true;
|
||||
DWORD wait_res = WaitForSingleObject( this->m_hThread, (DWORD)timeoutMsec );
|
||||
if( wait_res != WAIT_OBJECT_0 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "GameListener::waitStopped(): WaitForSingleObject() returned 0x%08X\n", wait_res );
|
||||
if( wait_res == WAIT_TIMEOUT ) log_error( LOG_DEBUG, "GameListener::waitStopped(): WAIT_TIMEOUT\n" );
|
||||
return false;
|
||||
}
|
||||
// wait OK, close kernel objects
|
||||
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
||||
// initialize self
|
||||
this->_initNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameListener::terminateThread()
|
||||
{
|
||||
if( this->m_hThread )
|
||||
{
|
||||
TerminateThread( this->m_hThread, 0xBAADF00D );
|
||||
CloseHandle( this->m_hThread );
|
||||
this->m_hThread = NULL;
|
||||
this->m_signal = 0;
|
||||
// thread resources
|
||||
if( m_listen_socket != INVALID_SOCKET )
|
||||
{
|
||||
//sock_tcp_close_shutdown( m_listen_socket, SD_BOTH );
|
||||
L2PNet_shutdown( m_listen_socket );
|
||||
L2PNet_closesocket( m_listen_socket );
|
||||
}
|
||||
m_listen_socket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
bool GameListener::isRunning() const
|
||||
{
|
||||
if( this->m_hThread != NULL ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameListener::_initNull()
|
||||
{
|
||||
m_hThread = NULL;
|
||||
m_signal = 0;
|
||||
m_sinfo.ip[0] = m_sinfo.ip[1] = m_sinfo.ip[2] = m_sinfo.ip[3] = 0;
|
||||
m_sinfo.port = 0;
|
||||
// thread resources
|
||||
m_listen_socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void GameListener::setPlayServerInfo( struct PlayServerInfo *pinfo )
|
||||
{
|
||||
if( !pinfo ) return;
|
||||
// copy struct :)
|
||||
memcpy( &(this->m_sinfo), pinfo, sizeof(struct PlayServerInfo) );
|
||||
// enable forcing game server IP:port Select
|
||||
if( g_cfg.ForceGameServerIP[0] && g_cfg.ForceGameServerPort )
|
||||
{
|
||||
in_addr force_addr;
|
||||
force_addr.s_addr = L2PNet_inet_addr( g_cfg.ForceGameServerIP );
|
||||
if( force_addr.s_addr == INADDR_NONE )
|
||||
{
|
||||
// try to resolve
|
||||
L2PNet_resolveHostname( g_cfg.ForceGameServerIP, &force_addr );
|
||||
}
|
||||
m_sinfo.ip[0] = force_addr.S_un.S_un_b.s_b1;
|
||||
m_sinfo.ip[1] = force_addr.S_un.S_un_b.s_b2;
|
||||
m_sinfo.ip[2] = force_addr.S_un.S_un_b.s_b3;
|
||||
m_sinfo.ip[3] = force_addr.S_un.S_un_b.s_b4;
|
||||
m_sinfo.port = g_cfg.ForceGameServerPort & 0x0000FFFF;
|
||||
log_error( LOG_WARNING, "GameListener: FORCED game server IP:port to %d.%d.%d.%d:%d\n",
|
||||
(int)m_sinfo.ip[0], (int)m_sinfo.ip[1], (int)m_sinfo.ip[2], (int)m_sinfo.ip[3],
|
||||
(int)m_sinfo.port );
|
||||
}
|
||||
//
|
||||
log_error( LOG_DEBUG, "GameListener: set play server address: %d.%d.%d.%d:%d\n",
|
||||
(int)m_sinfo.ip[0], (int)m_sinfo.ip[1], (int)m_sinfo.ip[2], (int)m_sinfo.ip[3],
|
||||
(int)m_sinfo.port );
|
||||
}
|
||||
|
||||
void GameListener::getPlayServerInfo( struct PlayServerInfo *pinfo ) const
|
||||
{
|
||||
if( !pinfo ) return;
|
||||
memcpy( pinfo, &(this->m_sinfo), sizeof(struct PlayServerInfo) );
|
||||
}
|
||||
43
l2detect/GameListener.h
Normal file
43
l2detect/GameListener.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef FAKEGAMELISTENER_H_
|
||||
#define FAKEGAMELISTENER_H_
|
||||
|
||||
struct PlayServerInfo
|
||||
{
|
||||
unsigned char ip[4];
|
||||
unsigned short int port;
|
||||
};
|
||||
|
||||
// signals to thread
|
||||
#define FLGS_STOP 1
|
||||
|
||||
class GameListener
|
||||
{
|
||||
friend void FGS_Thread_freeInfo( struct FLGT_INFO *pinfo );
|
||||
friend DWORD WINAPI FGS_Thread( LPVOID lpParam );
|
||||
public:
|
||||
GameListener();
|
||||
virtual ~GameListener();
|
||||
public:
|
||||
bool start();
|
||||
void signal( unsigned int code ) { this->m_signal = code; }
|
||||
void signalStop() { this->signal( FLGS_STOP ); }
|
||||
bool waitStopped( unsigned int timeoutMsec );
|
||||
unsigned int getLastSignal() const { return this->m_signal; }
|
||||
void setLastSignal( unsigned int code ) { this->m_signal = code; }
|
||||
void terminateThread();
|
||||
public:
|
||||
bool isRunning() const;
|
||||
public:
|
||||
void setPlayServerInfo( struct PlayServerInfo *pinfo );
|
||||
void getPlayServerInfo( struct PlayServerInfo *pinfo ) const;
|
||||
protected:
|
||||
void _initNull();
|
||||
protected:
|
||||
HANDLE m_hThread;
|
||||
unsigned int m_signal;
|
||||
struct PlayServerInfo m_sinfo;
|
||||
// thread resources
|
||||
SOCKET m_listen_socket;
|
||||
};
|
||||
|
||||
#endif /*FAKEGAMELISTENER_H_*/
|
||||
10
l2detect/GroundItem.cpp
Normal file
10
l2detect/GroundItem.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "stdafx.h"
|
||||
#include "GroundItem.h"
|
||||
|
||||
void GroundItem::setUnused()
|
||||
{
|
||||
L2Object::setUnused();
|
||||
itemID = 0;
|
||||
stackable = 0;
|
||||
count = 0;
|
||||
}
|
||||
17
l2detect/GroundItem.h
Normal file
17
l2detect/GroundItem.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef H_GROUNDITEM
|
||||
#define H_GROUNDITEM
|
||||
|
||||
class GroundItem: public L2Object
|
||||
{
|
||||
public:
|
||||
GroundItem() { setUnused(); }
|
||||
~GroundItem() { setUnused(); }
|
||||
public:
|
||||
virtual void setUnused();
|
||||
public:
|
||||
unsigned int itemID;
|
||||
int stackable;
|
||||
unsigned long long int count;
|
||||
};
|
||||
|
||||
#endif
|
||||
274
l2detect/HWID.cpp
Normal file
274
l2detect/HWID.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "HWID.h"
|
||||
#include "base64.h"
|
||||
#include "L2Detect_auth.h"
|
||||
|
||||
const int max_pbsi = 3;
|
||||
|
||||
struct partial_boot_sector_info
|
||||
{
|
||||
LPSTR Fs; // file system name
|
||||
DWORD FsOffs; // offset of file system name in the boot sector
|
||||
DWORD SerialOffs; // offset of the serialnumber in the boot sector
|
||||
};
|
||||
|
||||
void read_MBR( unsigned char *outbuffer )
|
||||
{
|
||||
//HANDLE hFile = CreateFileW( L"\\\\.\\PhysicalDrive0",
|
||||
HANDLE hFile = CreateFileW( L"\\\\.\\c:",
|
||||
GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if( hFile == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
log_error( LOG_ERROR, "read_MBR(): CreateFile failed, errCode = %u\n", (unsigned)le );
|
||||
return;
|
||||
}
|
||||
DWORD dwRead = 0;
|
||||
if( ReadFile( hFile, outbuffer, 512, &dwRead, NULL ) == 0 )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
log_error( LOG_ERROR, "read_MBR(): ReadFile failed, errCode = %u\n", (unsigned)le );
|
||||
}
|
||||
CloseHandle( hFile );
|
||||
log_error( LOG_DEBUG, "read_MBR(): ReadFile read %u bytes\n", (unsigned)dwRead );
|
||||
}
|
||||
|
||||
void getHDDInfo( char *volumeSN, char *hwSN, char *fsName )
|
||||
{
|
||||
char szVolumeName[256] = {0};
|
||||
char szFSName[256] = {0};
|
||||
unsigned long dwVolumeSN = 0, dwMaxComponentLen = 0, dwFSFlags = 0;
|
||||
if( !GetVolumeInformationA( "C:\\", szVolumeName, 256, &dwVolumeSN,
|
||||
&dwMaxComponentLen, &dwFSFlags, szFSName, 256 ) ) return;
|
||||
|
||||
unsigned char MBR[512];
|
||||
memset( MBR, 0, sizeof(MBR) );
|
||||
read_MBR( MBR );
|
||||
|
||||
partial_boot_sector_info pbsi[max_pbsi] =
|
||||
{
|
||||
{"FAT32", 0x52, 0x43},
|
||||
{"FAT", 0x36, 0x27},
|
||||
{"NTFS", 0x03, 0x48}
|
||||
};
|
||||
|
||||
// try to search for a valid boot sector
|
||||
int i = 0;
|
||||
for( i=0; i<max_pbsi; i++)
|
||||
{
|
||||
if( strncmp( pbsi[i].Fs, (const char *)(MBR + pbsi[i].FsOffs), strlen( pbsi[i].Fs ) ) == 0 )
|
||||
{
|
||||
// we found a valid signature
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i >= max_pbsi )
|
||||
{
|
||||
log_error( LOG_ERROR, "getHDDInfo(): Cannot get serial number of this file system!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD dwHWSN = 0;
|
||||
memcpy( (void *)(&dwHWSN), (const void *)(MBR + pbsi[i].SerialOffs), sizeof(dwHWSN) );
|
||||
|
||||
// out data
|
||||
sprintf( volumeSN, "%08X", dwVolumeSN );
|
||||
sprintf( hwSN, "%08X", dwHWSN );
|
||||
strcpy( fsName, szFSName );
|
||||
}
|
||||
|
||||
void getBIOSInfo( char *out_ver )
|
||||
{
|
||||
out_ver[0] = 0;
|
||||
HKEY hKey = NULL;
|
||||
char systemBIOSdate[256];
|
||||
char systemBIOSversion[1024];
|
||||
//char out_ver[1024] = {0};
|
||||
memset( systemBIOSdate, 0, sizeof(systemBIOSdate) );
|
||||
memset( systemBIOSversion, 0, sizeof(systemBIOSversion) );
|
||||
LONG result = 0;
|
||||
// support Wow64
|
||||
if( (result = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System", 0, KEY_READ | KEY_WOW64_64KEY, &hKey )) == 0 )
|
||||
{
|
||||
DWORD dwType = REG_SZ;
|
||||
DWORD dwCbData = sizeof(systemBIOSdate);
|
||||
// bios date
|
||||
if( (result = RegQueryValueExA( hKey, "SystemBiosDate", NULL, &dwType, (LPBYTE)systemBIOSdate, &dwCbData )) == 0 )
|
||||
{
|
||||
strcat( out_ver, systemBIOSdate );
|
||||
strcat( out_ver, "; " );
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegQueryValueExA()", (DWORD)result );
|
||||
// Windows x64 or 2003 versions? other reg keys:
|
||||
// HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSReleaseDate
|
||||
// HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSVersion
|
||||
HKEY hKey2 = NULL;
|
||||
result = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", 0, KEY_READ | KEY_WOW64_64KEY, &hKey2 );
|
||||
if( result == 0 )
|
||||
{
|
||||
dwType = REG_SZ;
|
||||
dwCbData = sizeof(systemBIOSdate);
|
||||
result = RegQueryValueExA( hKey2, "BIOSReleaseDate", NULL, &dwType, (LPBYTE)systemBIOSdate, &dwCbData );
|
||||
if( result == 0 )
|
||||
{
|
||||
strcat( out_ver, systemBIOSdate );
|
||||
strcat( out_ver, "; " );
|
||||
}
|
||||
else
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegQueryValueExA() (win64)", (DWORD)result );
|
||||
RegCloseKey( hKey2 );
|
||||
}
|
||||
else
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegOpenKeyExA() (win64)", (DWORD)result );
|
||||
}
|
||||
//
|
||||
// bios version
|
||||
dwType = REG_MULTI_SZ;
|
||||
dwCbData = sizeof(systemBIOSversion);
|
||||
if( (result = RegQueryValueExA( hKey, "SystemBiosVersion", NULL, &dwType, (LPBYTE)systemBIOSversion, &dwCbData )) == 0 )
|
||||
{
|
||||
strcat( out_ver, systemBIOSversion );
|
||||
char *pstr = systemBIOSversion + strlen(systemBIOSversion) + 1;
|
||||
if( *pstr )
|
||||
{
|
||||
strcat( out_ver, "; " );
|
||||
strcat( out_ver, pstr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegQueryValueExA()", (DWORD)result );
|
||||
// Windows x64 or 2003 versions? other reg keys
|
||||
// HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSReleaseDate
|
||||
// HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSVersion
|
||||
HKEY hKey2 = NULL;
|
||||
result = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", 0, KEY_READ | KEY_WOW64_64KEY, &hKey2 );
|
||||
if( result == 0 )
|
||||
{
|
||||
dwType = REG_SZ; // not REG_MULTI_SZ
|
||||
dwCbData = sizeof(systemBIOSversion);
|
||||
result = RegQueryValueExA( hKey2, "BIOSVersion", NULL, &dwType, (LPBYTE)systemBIOSversion, &dwCbData );
|
||||
if( result == 0 )
|
||||
strcat( out_ver, systemBIOSversion );
|
||||
else
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegQueryValueExA() (win64)", (DWORD)result );
|
||||
RegCloseKey( hKey2 );
|
||||
}
|
||||
else
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegOpenKeyExA() (win64)", (DWORD)result );
|
||||
}
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
else
|
||||
ErrorLogger_LogLastError( "getBIOSInfo(): RegOpenKeyExA", (DWORD)result );
|
||||
}
|
||||
|
||||
void getOSInfo( char *os_info )
|
||||
{
|
||||
OSVERSIONINFOEXA os;
|
||||
memset( &os, 0, sizeof(os) );
|
||||
os.dwOSVersionInfoSize = sizeof(os);
|
||||
if( GetVersionExA( (OSVERSIONINFOA *)&os ) )
|
||||
{
|
||||
sprintf( os_info, "%d.%d.%d sp %d.%d",
|
||||
os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber,
|
||||
(int)os.wServicePackMajor, (int)os.wServicePackMinor );
|
||||
}
|
||||
else log_error( LOG_ERROR, "getOSInfo(): GetVersionExA(): error!\n" );
|
||||
}
|
||||
|
||||
void getCPUInfo( char *cpu )
|
||||
{
|
||||
cpu[0] = 0;
|
||||
HKEY hKey = NULL;
|
||||
char str[512] = {0};
|
||||
if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey ) == 0 )
|
||||
{
|
||||
DWORD dwType = REG_SZ;
|
||||
DWORD dwCbData = sizeof(str);
|
||||
// vendor id
|
||||
if( RegQueryValueExA( hKey, "VendorIdentifier", NULL, &dwType, (LPBYTE)str, &dwCbData ) == 0 )
|
||||
{
|
||||
strcat( cpu, str );
|
||||
strcat( cpu, " " );
|
||||
} else log_error( LOG_ERROR, "getCPUInfo(): RegQueryValueExA(): error!\n" );
|
||||
// name
|
||||
dwType = REG_SZ;
|
||||
dwCbData = sizeof(str);
|
||||
if( RegQueryValueExA( hKey, "ProcessorNameString", NULL, &dwType, (LPBYTE)str, &dwCbData ) == 0 )
|
||||
{
|
||||
strcat( cpu, str );
|
||||
} else log_error( LOG_ERROR, "getCPUInfo(): RegQueryValueExA(): error!\n" );
|
||||
// id
|
||||
dwType = REG_SZ;
|
||||
dwCbData = sizeof(str);
|
||||
if( RegQueryValueExA( hKey, "Identifier", NULL, &dwType, (LPBYTE)str, &dwCbData ) == 0 )
|
||||
{
|
||||
strcat( cpu, str );
|
||||
} else log_error( LOG_ERROR, "getCPUInfo(): RegQueryValueExA(): error!\n" );
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
else log_error( LOG_ERROR, "getCPUInfo(): RegOpenKeyExA(): error!\n" );
|
||||
}
|
||||
|
||||
void convert_to_urlsafe( char *s )
|
||||
{
|
||||
/*
|
||||
* use '-' and '_' instead of '+' and '/'
|
||||
* no line feeds
|
||||
* padding character is '*' instead of '='
|
||||
*/
|
||||
while( (*s) )
|
||||
{
|
||||
if( (*s) == '+' ) (*s) = '-';
|
||||
if( (*s) == '/' ) (*s) = '_';
|
||||
if( (*s) == '=' ) (*s) = '*';
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
int getLocalHWID( char *out )
|
||||
{
|
||||
char globalIDString[4096] = {0};
|
||||
char based[4096] = {0};
|
||||
char volumeSN[256] = {0}, hwSN[256] = {0}, fsName[256] = {0};
|
||||
char biosInfo[1024] = {0};
|
||||
char os_info[1024] = {0};
|
||||
char cpu_info[1024] = {0};
|
||||
|
||||
getHDDInfo( volumeSN, hwSN, fsName );
|
||||
getBIOSInfo( biosInfo );
|
||||
getOSInfo( os_info );
|
||||
getCPUInfo( cpu_info );
|
||||
sprintf( globalIDString, "%s|%s|%s|%s|%s|%s", volumeSN, hwSN, fsName, biosInfo, os_info, cpu_info );
|
||||
log_error( LOG_DEBUG, "HWID: [%s]\n", globalIDString );
|
||||
base64_encode_string( globalIDString, strlen(globalIDString), based );
|
||||
|
||||
convert_to_urlsafe( based );
|
||||
|
||||
strcpy( out, based );
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool VerifyHWID()
|
||||
{
|
||||
char localHWID[4096];
|
||||
char setHWID[4096];
|
||||
memset( localHWID, 0, sizeof(localHWID) );
|
||||
memset( setHWID, 0, sizeof(setHWID) );
|
||||
getLocalHWID( localHWID );
|
||||
//getHWID( setHWID );
|
||||
//log_error( LOG_DEBUG, "Verify HWID: [%s] == [%s] ?...\n", localHWID, setHWID );
|
||||
if( strcmp( localHWID, setHWID ) == 0 )
|
||||
{
|
||||
log_error( LOG_OK, "HWID verify OK\n" );
|
||||
return true;
|
||||
}
|
||||
log_error( LOG_ERROR, "HWID verify error!\n" );
|
||||
return false;
|
||||
}
|
||||
6
l2detect/HWID.h
Normal file
6
l2detect/HWID.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_HWID
|
||||
#define H_HWID
|
||||
|
||||
bool VerifyHWID();
|
||||
|
||||
#endif
|
||||
496
l2detect/HealItemsTable.cpp
Normal file
496
l2detect/HealItemsTable.cpp
Normal file
@@ -0,0 +1,496 @@
|
||||
#include "stdafx.h"
|
||||
#include "HealItemsTable.h"
|
||||
#include "utils.h"
|
||||
#include "Logger.h"
|
||||
|
||||
HealItem::HealItem()
|
||||
{
|
||||
itemName[0] = 0;
|
||||
itemID = reuseDelayMsec = 0;
|
||||
priority = 0;
|
||||
lastUseTime = 0;
|
||||
percentUse = 0;
|
||||
}
|
||||
|
||||
HealItem::HealItem( const HealItem &other )
|
||||
{
|
||||
strcpy( itemName, other.itemName );
|
||||
itemID = other.itemID;
|
||||
reuseDelayMsec = other.reuseDelayMsec;
|
||||
priority = other.priority;
|
||||
lastUseTime = other.lastUseTime;
|
||||
percentUse = other.percentUse;
|
||||
}
|
||||
|
||||
/*HealItem& HealItem::operator=( const HealItem& other )
|
||||
{
|
||||
strcpy( itemName, other.itemName );
|
||||
itemID = other.itemID;
|
||||
reuseDelaySecs = other.reuseDelaySecs;
|
||||
priority = other.priority;
|
||||
lastUseTime = other.lastUseTime;
|
||||
return (*this);
|
||||
}*/
|
||||
|
||||
void HealItem::GetItemNameW( wchar_t *out )
|
||||
{
|
||||
if( !out ) return;
|
||||
out[0] = 0;
|
||||
if( itemName[0] == 0 ) return;
|
||||
MultiByteToWideChar( CP_ACP, 0, itemName, -1, out, 127 );
|
||||
}
|
||||
|
||||
|
||||
HealItemsTable::HealItemsTable()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
HealItemsTable::~HealItemsTable()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void HealItemsTable::clear()
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<MAXNUMHEALITEMS; i++ )
|
||||
{
|
||||
hp_healers[i].itemID = mp_healers[i].itemID = cp_healers[i].itemID = 0;
|
||||
}
|
||||
enableHealHP = true;
|
||||
enableHealMP = true;
|
||||
enableHealCP = true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::LoadFromFile( const char *fileName )
|
||||
{
|
||||
if( !fileName ) return false;
|
||||
clear();
|
||||
int last_added = 0;
|
||||
FILE *f = fopen( fileName, "rt" );
|
||||
if( !f ) return false;
|
||||
char line[512] = {0};
|
||||
//
|
||||
char itemName[128] = {0};
|
||||
unsigned int itemID = 0;
|
||||
unsigned int reuseDelay = 0;
|
||||
int priority = 0;
|
||||
int percentUse = 0;
|
||||
//
|
||||
int cur_read = 0;
|
||||
const int READ_CP = 1;
|
||||
const int READ_HP = 2;
|
||||
const int READ_MP = 3;
|
||||
//
|
||||
char *token;
|
||||
char delim[] = "=;\r\n";
|
||||
//
|
||||
while( !feof( f ) )
|
||||
{
|
||||
if( freadline( f, line, sizeof(line)-1 ) == 0 ) continue;
|
||||
if( line[0] == '#' ) continue;
|
||||
if( strcmp( line, "[CP healers]" ) == 0 )
|
||||
{
|
||||
cur_read = READ_CP;
|
||||
last_added = 0;
|
||||
continue;
|
||||
}
|
||||
if( strcmp( line, "[HP healers]" ) == 0 )
|
||||
{
|
||||
cur_read = READ_HP;
|
||||
last_added = 0;
|
||||
continue;
|
||||
}
|
||||
if( strcmp( line, "[MP healers]" ) == 0 )
|
||||
{
|
||||
cur_read = READ_MP;
|
||||
last_added = 0;
|
||||
continue;
|
||||
}
|
||||
if( !strchr( line, '=' ) ) continue;
|
||||
|
||||
if( strstr( line, "CPHealEnable" ) == line )
|
||||
{
|
||||
token = strtok( line, "=" );
|
||||
if( token ) token = strtok( NULL, "=" );
|
||||
if( token ) sscanf( token, "%d", &(this->enableHealCP) );
|
||||
continue;
|
||||
}
|
||||
if( strstr( line, "HPHealEnable" ) == line )
|
||||
{
|
||||
token = strtok( line, "=" );
|
||||
if( token ) token = strtok( NULL, "=" );
|
||||
if( token ) sscanf( token, "%d", &(this->enableHealHP) );
|
||||
continue;
|
||||
}
|
||||
if( strstr( line, "MPHealEnable" ) == line )
|
||||
{
|
||||
token = strtok( line, "=" );
|
||||
if( token ) token = strtok( NULL, "=" );
|
||||
if( token ) sscanf( token, "%d", &(this->enableHealMP) );
|
||||
continue;
|
||||
}
|
||||
|
||||
// token itemName
|
||||
token = strtok( line, delim );
|
||||
if( !token ) continue;
|
||||
strcpy( itemName, token );
|
||||
// token itemID
|
||||
token = strtok( NULL, delim );
|
||||
if( !token ) continue;
|
||||
sscanf( token, "%u", &itemID );
|
||||
// token reuseDelay
|
||||
token = strtok( NULL, delim );
|
||||
if( !token ) continue;
|
||||
sscanf( token, "%u", &reuseDelay );
|
||||
// token priority
|
||||
token = strtok( NULL, delim );
|
||||
if( !token ) continue;
|
||||
sscanf( token, "%d", &priority );
|
||||
// token percentUse
|
||||
token = strtok( NULL, delim );
|
||||
if( !token ) continue;
|
||||
sscanf( token, "%d", &percentUse );
|
||||
// log
|
||||
//switch( cur_read )
|
||||
//{
|
||||
//case READ_HP: log_error( LOG_USERAI, "HealItemTable: READ_HP: %s [ID=%u] (%d sec, %d priotiy)\n", itemName, itemID, reuseDelay, priority ); break;
|
||||
//case READ_MP: log_error( LOG_USERAI, "HealItemTable: READ_MP: %s [ID=%u] (%d sec, %d priotiy)\n", itemName, itemID, reuseDelay, priority ); break;
|
||||
//case READ_CP: log_error( LOG_USERAI, "HealItemTable: READ_CP: %s [ID=%u] (%d sec, %d priotiy)\n", itemName, itemID, reuseDelay, priority ); break;
|
||||
//}
|
||||
//
|
||||
//add
|
||||
switch( cur_read )
|
||||
{
|
||||
case READ_HP:
|
||||
{
|
||||
strcpy( hp_healers[last_added].itemName, itemName );
|
||||
hp_healers[last_added].itemID = itemID;
|
||||
hp_healers[last_added].reuseDelayMsec = reuseDelay;
|
||||
hp_healers[last_added].priority = priority;
|
||||
hp_healers[last_added].lastUseTime = 0;
|
||||
hp_healers[last_added].percentUse = percentUse;
|
||||
last_added++;
|
||||
} break;
|
||||
case READ_MP:
|
||||
{
|
||||
strcpy( mp_healers[last_added].itemName, itemName );
|
||||
mp_healers[last_added].itemID = itemID;
|
||||
mp_healers[last_added].reuseDelayMsec = reuseDelay;
|
||||
mp_healers[last_added].priority = priority;
|
||||
mp_healers[last_added].lastUseTime = 0;
|
||||
mp_healers[last_added].percentUse = percentUse;
|
||||
last_added++;
|
||||
} break;
|
||||
case READ_CP:
|
||||
{
|
||||
strcpy( cp_healers[last_added].itemName, itemName );
|
||||
cp_healers[last_added].itemID = itemID;
|
||||
cp_healers[last_added].reuseDelayMsec = reuseDelay;
|
||||
cp_healers[last_added].priority = priority;
|
||||
cp_healers[last_added].lastUseTime = 0;
|
||||
cp_healers[last_added].percentUse = percentUse;
|
||||
last_added++;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
fclose( f );
|
||||
sort();
|
||||
return true;
|
||||
}
|
||||
|
||||
void HealItemsTable::sort()
|
||||
{
|
||||
int i, j;
|
||||
HealItem temp;
|
||||
// hp healers
|
||||
for( i=0; i<=(MAXNUMHEALITEMS-2); i++ )
|
||||
{
|
||||
for( j=i+1; j<=(MAXNUMHEALITEMS-1); j++ )
|
||||
{
|
||||
if( hp_healers[j].priority > hp_healers[i].priority )
|
||||
{
|
||||
// save temp
|
||||
//temp = hp_healers[i];
|
||||
strcpy( temp.itemName, hp_healers[i].itemName );
|
||||
temp.itemID = hp_healers[i].itemID;
|
||||
temp.priority = hp_healers[i].priority;
|
||||
temp.reuseDelayMsec = hp_healers[i].reuseDelayMsec;
|
||||
temp.percentUse = hp_healers[i].percentUse;
|
||||
// copy j -=> i
|
||||
//hp_healers[i] = hp_healers[j];
|
||||
strcpy( hp_healers[i].itemName, hp_healers[j].itemName );
|
||||
hp_healers[i].itemID = hp_healers[j].itemID;
|
||||
hp_healers[i].priority = hp_healers[j].priority;
|
||||
hp_healers[i].reuseDelayMsec = hp_healers[j].reuseDelayMsec;
|
||||
hp_healers[i].percentUse = hp_healers[j].percentUse;
|
||||
//restore i
|
||||
//hp_healers[j] = temp;
|
||||
strcpy( hp_healers[j].itemName, temp.itemName );
|
||||
hp_healers[j].itemID = temp.itemID;
|
||||
hp_healers[j].priority = temp.priority;
|
||||
hp_healers[j].reuseDelayMsec = temp.reuseDelayMsec;
|
||||
hp_healers[j].percentUse = temp.percentUse;
|
||||
}
|
||||
}
|
||||
}
|
||||
// mp healers
|
||||
for( i=0; i<=(MAXNUMHEALITEMS-2); i++ )
|
||||
{
|
||||
for( j=i+1; j<=(MAXNUMHEALITEMS-1); j++ )
|
||||
{
|
||||
if( mp_healers[j].priority > mp_healers[i].priority )
|
||||
{
|
||||
// save temp
|
||||
temp = mp_healers[i];
|
||||
// copy j -=> i
|
||||
mp_healers[i] = mp_healers[j];
|
||||
//restore i
|
||||
mp_healers[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
// cp healers
|
||||
for( i=0; i<=(MAXNUMHEALITEMS-2); i++ )
|
||||
{
|
||||
for( j=i+1; j<=(MAXNUMHEALITEMS-1); j++ )
|
||||
{
|
||||
if( cp_healers[j].priority > cp_healers[i].priority )
|
||||
{
|
||||
// save temp
|
||||
temp = cp_healers[i];
|
||||
// copy j -=> i
|
||||
cp_healers[i] = cp_healers[j];
|
||||
//restore i
|
||||
cp_healers[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HealItemsTable::getHPItem( int idx, HealItem& out )
|
||||
{
|
||||
if( (idx<0) || (idx>=MAXNUMHEALITEMS) ) return false;
|
||||
out.itemID = 0;
|
||||
out.itemName[0] = 0;
|
||||
if( hp_healers[idx].itemID == 0 ) return false;
|
||||
//out = hp_healers[idx];
|
||||
strcpy( out.itemName, hp_healers[idx].itemName );
|
||||
out.itemID = hp_healers[idx].itemID;
|
||||
out.lastUseTime = hp_healers[idx].lastUseTime;
|
||||
out.priority = hp_healers[idx].priority;
|
||||
out.reuseDelayMsec = hp_healers[idx].reuseDelayMsec;
|
||||
out.percentUse = hp_healers[idx].percentUse;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::getMPItem( int idx, HealItem& out )
|
||||
{
|
||||
if( (idx<0) || (idx>=MAXNUMHEALITEMS) ) return false;
|
||||
out.itemID = 0;
|
||||
out.itemName[0] = 0;
|
||||
if( mp_healers[idx].itemID == 0 ) return false;
|
||||
out = mp_healers[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::getCPItem( int idx, HealItem& out )
|
||||
{
|
||||
if( (idx<0) || (idx>=MAXNUMHEALITEMS) ) return false;
|
||||
out.itemID = 0;
|
||||
out.itemName[0] = 0;
|
||||
if( cp_healers[idx].itemID == 0 ) return false;
|
||||
out = cp_healers[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
// type: 0 - hp; 1 - mp; 2 - cp
|
||||
bool HealItemsTable::markUsedNow( HEALITEM_TYPE type, int idx, unsigned int tickCount )
|
||||
{
|
||||
if( (idx<0) || (idx>=MAXNUMHEALITEMS) ) return false;
|
||||
switch( type )
|
||||
{
|
||||
case HIT_HP:
|
||||
{
|
||||
if( hp_healers[idx].itemID == 0 ) return false;
|
||||
hp_healers[idx].lastUseTime = tickCount;
|
||||
} break;
|
||||
case HIT_MP:
|
||||
{
|
||||
if( mp_healers[idx].itemID == 0 ) return false;
|
||||
mp_healers[idx].lastUseTime = tickCount;
|
||||
} break;
|
||||
case HIT_CP:
|
||||
{
|
||||
if( cp_healers[idx].itemID == 0 ) return false;
|
||||
cp_healers[idx].lastUseTime = tickCount;
|
||||
} break;
|
||||
default: return false; break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::delItemFromTable( HEALITEM_TYPE type, int index )
|
||||
{
|
||||
if( (index<0) || (index>=MAXNUMHEALITEMS) ) return false;
|
||||
int i;
|
||||
switch( type )
|
||||
{
|
||||
case HIT_MARKUSED_HP:
|
||||
{
|
||||
hp_healers[index].itemID = 0;
|
||||
hp_healers[index].priority = 0;
|
||||
// shift
|
||||
i=index;
|
||||
while( i<=(MAXNUMHEALITEMS-2) )
|
||||
{
|
||||
hp_healers[i] = hp_healers[i+1];
|
||||
i++;
|
||||
}
|
||||
} break;
|
||||
case HIT_MARKUSED_MP:
|
||||
{
|
||||
mp_healers[index].itemID = 0;
|
||||
mp_healers[index].priority = 0;
|
||||
// shift
|
||||
i=index;
|
||||
while( i<=(MAXNUMHEALITEMS-2) )
|
||||
{
|
||||
mp_healers[i] = mp_healers[i+1];
|
||||
i++;
|
||||
}
|
||||
} break;
|
||||
case HIT_MARKUSED_CP:
|
||||
{
|
||||
cp_healers[index].itemID = 0;
|
||||
cp_healers[index].priority = 0;
|
||||
// shift
|
||||
i=index;
|
||||
while( i<=(MAXNUMHEALITEMS-2) )
|
||||
{
|
||||
cp_healers[i] = cp_healers[i+1];
|
||||
i++;
|
||||
}
|
||||
} break;
|
||||
default: return false; break;
|
||||
}
|
||||
//sort();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::SaveToFile( const char *fileName )
|
||||
{
|
||||
if( !fileName ) return false;
|
||||
FILE *f = fopen( fileName, "wt" );
|
||||
if( !f ) return false;
|
||||
|
||||
// header
|
||||
fprintf( f,
|
||||
"# Format:\n"
|
||||
"# Item Name=ItemID;reuseDelay(milliSeconds);priority;activatePercent\n"
|
||||
"# No spaces between '=', ';' !\n"
|
||||
"# priority is number between 1 and 100, determines which item will be used first\n"
|
||||
"# priority 0 means 'do not use this item' :)\n"
|
||||
"# ActivatePercent is stat value in percent from maximum, when this item can be used\n"
|
||||
"\n" );
|
||||
|
||||
int i;
|
||||
|
||||
// CP healers
|
||||
fprintf( f,
|
||||
"[CP healers]\n"
|
||||
"CPHealEnable=%d\n", this->enableHealCP );
|
||||
for( i=0; i<MAXNUMHEALITEMS; i++ )
|
||||
{
|
||||
if( this->cp_healers[i].itemID == 0 ) continue;
|
||||
fprintf( f, "%s=%u;%u;%d;%d\n",
|
||||
this->cp_healers[i].itemName,
|
||||
this->cp_healers[i].itemID,
|
||||
this->cp_healers[i].reuseDelayMsec,
|
||||
this->cp_healers[i].priority,
|
||||
this->cp_healers[i].percentUse );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
|
||||
// HP healers
|
||||
fprintf( f,
|
||||
"[HP healers]\n"
|
||||
"HPHealEnable=%d\n", this->enableHealHP );
|
||||
for( i=0; i<MAXNUMHEALITEMS; i++ )
|
||||
{
|
||||
if( this->hp_healers[i].itemID == 0 ) continue;
|
||||
fprintf( f, "%s=%u;%u;%d;%d\n",
|
||||
this->hp_healers[i].itemName,
|
||||
this->hp_healers[i].itemID,
|
||||
this->hp_healers[i].reuseDelayMsec,
|
||||
this->hp_healers[i].priority,
|
||||
this->hp_healers[i].percentUse );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
|
||||
// MP healers
|
||||
fprintf( f,
|
||||
"[MP healers]\n"
|
||||
"MPHealEnable=%d\n", this->enableHealMP );
|
||||
for( i=0; i<MAXNUMHEALITEMS; i++ )
|
||||
{
|
||||
if( this->mp_healers[i].itemID == 0 ) continue;
|
||||
fprintf( f, "%s=%u;%u;%d;%d\n",
|
||||
this->mp_healers[i].itemName,
|
||||
this->mp_healers[i].itemID,
|
||||
this->mp_healers[i].reuseDelayMsec,
|
||||
this->mp_healers[i].priority,
|
||||
this->mp_healers[i].percentUse );
|
||||
}
|
||||
fprintf( f, "\n" );
|
||||
|
||||
fclose( f );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::addHealItem( HEALITEM_TYPE type, const HealItem *example )
|
||||
{
|
||||
if( !example ) return false;
|
||||
int free_idx = -1;
|
||||
int i;
|
||||
unsigned int itemID;
|
||||
for( i=0; i<MAXNUMHEALITEMS; i++ )
|
||||
{
|
||||
itemID = 0;
|
||||
switch( type )
|
||||
{
|
||||
case HIT_HP: itemID = hp_healers[i].itemID; break;
|
||||
case HIT_MP: itemID = mp_healers[i].itemID; break;
|
||||
case HIT_CP: itemID = cp_healers[i].itemID; break;
|
||||
}
|
||||
if( itemID == 0 )
|
||||
{
|
||||
free_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( free_idx == -1 ) return false;
|
||||
switch( type )
|
||||
{
|
||||
case HIT_HP: hp_healers[free_idx] = (*example); break;
|
||||
case HIT_MP: mp_healers[free_idx] = (*example); break;
|
||||
case HIT_CP: cp_healers[free_idx] = (*example); break;
|
||||
}
|
||||
sort();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HealItemsTable::setHealItem( HEALITEM_TYPE type, int idx, const HealItem *example )
|
||||
{
|
||||
if( !example ) return false;
|
||||
if( (idx<0) || (idx>=MAXNUMHEALITEMS) ) return false;
|
||||
switch( type )
|
||||
{
|
||||
case HIT_HP: hp_healers[idx] = (*example); break;
|
||||
case HIT_MP: mp_healers[idx] = (*example); break;
|
||||
case HIT_CP: cp_healers[idx] = (*example); break;
|
||||
default: return false; break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
66
l2detect/HealItemsTable.h
Normal file
66
l2detect/HealItemsTable.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef H_HEALITEMS_TABLE
|
||||
#define H_HEALITEMS_TABLE
|
||||
|
||||
class HealItem
|
||||
{
|
||||
public:
|
||||
HealItem();
|
||||
HealItem( const HealItem &other );
|
||||
//HealItem& operator=( const HealItem& other );
|
||||
public:
|
||||
void GetItemNameW( wchar_t *out );
|
||||
public:
|
||||
char itemName[128];
|
||||
unsigned int itemID;
|
||||
unsigned int reuseDelayMsec;
|
||||
int priority;
|
||||
unsigned int lastUseTime;
|
||||
int percentUse;
|
||||
};
|
||||
|
||||
#define MAXNUMHEALITEMS 16
|
||||
// markUsedNow constants
|
||||
#define HIT_MARKUSED_HP 0
|
||||
#define HIT_MARKUSED_MP 1
|
||||
#define HIT_MARKUSED_CP 2
|
||||
|
||||
class HealItemsTable
|
||||
{
|
||||
public:
|
||||
typedef enum eHEALITEM_TYPE
|
||||
{
|
||||
HIT_HP = 0,
|
||||
HIT_MP,
|
||||
HIT_CP
|
||||
} HEALITEM_TYPE;
|
||||
public:
|
||||
HealItemsTable();
|
||||
~HealItemsTable();
|
||||
public:
|
||||
void clear();
|
||||
bool LoadFromFile( const char *fileName );
|
||||
bool SaveToFile( const char *fileName );
|
||||
bool getHPItem( int idx, HealItem& out );
|
||||
bool getMPItem( int idx, HealItem& out );
|
||||
bool getCPItem( int idx, HealItem& out );
|
||||
|
||||
// type: 0 - hp; 1 - mp; 2 - cp
|
||||
bool markUsedNow( HEALITEM_TYPE type, int idx, unsigned int tickCount );
|
||||
|
||||
bool delItemFromTable( HEALITEM_TYPE type, int index );
|
||||
bool addHealItem( HEALITEM_TYPE type, const HealItem *example );
|
||||
bool setHealItem( HEALITEM_TYPE type, int idx, const HealItem *example );
|
||||
|
||||
public:
|
||||
int enableHealHP;
|
||||
int enableHealMP;
|
||||
int enableHealCP;
|
||||
|
||||
protected:
|
||||
HealItem hp_healers[MAXNUMHEALITEMS];
|
||||
HealItem mp_healers[MAXNUMHEALITEMS];
|
||||
HealItem cp_healers[MAXNUMHEALITEMS];
|
||||
void sort();
|
||||
};
|
||||
|
||||
#endif
|
||||
84
l2detect/L2Detect.ini
Normal file
84
l2detect/L2Detect.ini
Normal file
@@ -0,0 +1,84 @@
|
||||
# ===============
|
||||
# Network setup
|
||||
# ===============
|
||||
|
||||
# =======================
|
||||
# Listen ports setup
|
||||
# * Ports on which program will bind listen sockets - local address
|
||||
FakeListenLoginIP = 127.0.0.1
|
||||
FakeListenLoginPort = 2106
|
||||
FakeListenGameIP = 127.0.0.1
|
||||
FakeListenGamePort = 8777
|
||||
|
||||
# ========================
|
||||
# Forward connection to
|
||||
# * Where to redirect login connection - IP/hostname & port
|
||||
RealLoginServerIP = 217.23.91.18
|
||||
RealLoginServerPort = 2106
|
||||
|
||||
# ===========================
|
||||
# Catch game server traffic
|
||||
# * Which Game server's IP and port will be replaced in ServerList packet
|
||||
PlayGameServerNo = 1
|
||||
|
||||
# =============
|
||||
# Logging Setup
|
||||
# =============
|
||||
|
||||
# =====================================
|
||||
# Warn messages level printed to stdout
|
||||
# 0 - no messages to screen
|
||||
# 1 - errors only (Recommended :)
|
||||
# 2 - errors, warnings
|
||||
# 3 - errors, warnings, packet names
|
||||
# 4 - errors, warnings, packet names, debug messages
|
||||
# 5 - errors, warnings, packet names, debug messages, packet dumps
|
||||
# Default: 1; it cannot be <0, but can be very big number. [0..0xFFFFFFFF]
|
||||
WarnMessageLevel = 4
|
||||
|
||||
# ====================================
|
||||
# If enabled, program will print something like:
|
||||
# [PACKET] Unknown packet 00 in state: IN_GAME
|
||||
# in WarnMessageLevel >= 3
|
||||
WarnUnknownPacketsToStdout = 0
|
||||
|
||||
# ====================================
|
||||
# Dump "unknown" packets to console window? 0-no, 1-yes (Default: 0, not display)
|
||||
DumpUnknownToStdout = 0
|
||||
|
||||
# ====================================
|
||||
# Enable or disable logging of Game Server packets 0-disable, 1-enable (Default: 0, disable)
|
||||
LogGamePackets = 0
|
||||
|
||||
# ====================================
|
||||
# File name prefix for log file with game server packets log
|
||||
# (file name will look like prefix_XXXXXXXX.txt, where XXX-current date/time unix timestamp)
|
||||
# Default: prefix_
|
||||
LogGameFileNamePrefix = l2fan_
|
||||
|
||||
# ==========
|
||||
# Hacks!!!!
|
||||
# ==========
|
||||
|
||||
# ========================================
|
||||
# Enable or disable game packets modifying
|
||||
# - If disabled (0), only passive sniffing if possible, NO ANY HACKS will work
|
||||
# - If enabled (1), packet-level hacks WILL work. This setting is REQUIRED to be set to ENABLED
|
||||
# if you want any hacks to work
|
||||
# - 0-disable, 1-enable; (Default: 0, disable, passive SNIFFING ONLY)
|
||||
EnableModifyGameTraffic = 1
|
||||
|
||||
# !!!!! Any hacks below will not work, if EnableModifyGameTraffic is set to 0 !!!!!
|
||||
|
||||
# =====================================================================
|
||||
# * Override game protocol version: change game protocol version number
|
||||
# * in C->S ProtocolVersion packet to given number.
|
||||
# * Value: 0 - disable this; any other number greater than 0: override to this number
|
||||
# * Default: 0
|
||||
OverrideGameProtocolVersion = 12
|
||||
# Help on protocol versions (Official server):
|
||||
# - T1 Kamael - 828
|
||||
# - T1.5 Hellbound - 831 ?
|
||||
# - T2 Gracia live - 851
|
||||
# - T2.2 Gracia Part 2 - ???
|
||||
# - T2.3 Gracia Final - ???
|
||||
103
l2detect/L2Detect.rc
Normal file
103
l2detect/L2Detect.rc
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "resource.h"
|
||||
#include "targetver.h"
|
||||
#include <windows.h>
|
||||
#define IDC_STATIC -1
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||
|
||||
// common controls manifest
|
||||
2 RT_MANIFEST "res\\xp_manifest.xml"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Dialogs
|
||||
|
||||
IDD_ABOUTBOX DIALOGEX 0, 0, 212, 110
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About L2Detect"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "L2Detect, v 0.4",IDC_STATIC,75,18,114,8,SS_NOPREFIX
|
||||
LTEXT "Copyright (C) 2008 Lexx :)",IDC_STATIC,74,33,114,8
|
||||
DEFPUSHBUTTON "<22><>",IDOK,83,89,50,14,WS_GROUP
|
||||
LTEXT "Special thanks to: fyyre, DistortNeo, KyberPrizrak, AllCheats.ru, l2wh.com, l2jserver.com",IDC_STATIC,49,50,131,27
|
||||
ICON IDI_L2_BLACK,IDC_STATIC,25,15,21,20
|
||||
END
|
||||
|
||||
|
||||
IDD_CONFIG DIALOGEX 0,0,332,261
|
||||
CAPTION "Network/Protocol Setup"
|
||||
FONT 8,"MS Shell Dlg",400,0,1
|
||||
STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME|DS_SETFONT|DS_FIXEDSYS
|
||||
BEGIN
|
||||
CONTROL "OK",IDOK,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_DEFPUSHBUTTON,208,241,50,15
|
||||
CONTROL "Cancel",IDCANCEL,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,262,241,50,15
|
||||
CONTROL "OverrideGameProtocolVersion:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,16,84,100,9
|
||||
CONTROL "",IDC_E_OVERRIDE_GPV,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,120,81,40,15,WS_EX_CLIENTEDGE
|
||||
CONTROL "Logging level:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,186,127,46,9
|
||||
CONTROL "Enable modify Game Server Traffic",IDC_C_ENABLE_MODGT,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,180,81,128,11
|
||||
CONTROL "",IDC_CB_LOGLEVEL,"ComboBox",WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|CBS_DROPDOWNLIST,258,127,60,87
|
||||
CONTROL "ThreadPriorityRaiseEnable",IDC_C_ENABLE_THREADPRI,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,180,96,100,11
|
||||
CONTROL "L2Walker_Fix_MoveBackwardToLocation",IDC_C_L2WMOVEFIX,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,16,144,146,11
|
||||
CONTROL "Ports Setup",IDC_STATIC,"Button",WS_CHILD|WS_VISIBLE|BS_GROUPBOX,10,192,320,46
|
||||
CONTROL "Listen Login Port:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,18,206,56,9
|
||||
CONTROL "Listen Game Port:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,18,219,58,9
|
||||
CONTROL "",IDC_E_FLPORT,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,82,201,36,15,WS_EX_CLIENTEDGE
|
||||
CONTROL "",IDC_E_FGPORT,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,82,217,36,15,WS_EX_CLIENTEDGE
|
||||
CONTROL "Real Login Server:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,126,203,60,9
|
||||
CONTROL "",IDC_E_REALIP,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,196,201,84,15,WS_EX_CLIENTEDGE
|
||||
CONTROL ":",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,284,201,8,9
|
||||
CONTROL "",IDC_E_REALPORT,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,290,201,32,15,WS_EX_CLIENTEDGE
|
||||
CONTROL "Apply :)",IDC_APPLY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,152,241,50,15
|
||||
CONTROL "Log Game Packets",IDC_C_LOGGAMEP,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,184,142,128,11
|
||||
CONTROL "Log File Name Prefix:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,184,158,68,9
|
||||
CONTROL "",IDC_E_LOGFNPREFIX,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,258,155,60,15,WS_EX_CLIENTEDGE
|
||||
CONTROL "Lineage II Server Protocol Version:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,20,16,112,8
|
||||
CONTROL "",IDC_CB_L2VER,"ComboBox",WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|CBS_DROPDOWNLIST,150,14,172,70
|
||||
CONTROL "Lineage II Client Version:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,20,31,82,9
|
||||
CONTROL "",IDC_CB_L2CVER,"ComboBox",WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|CBS_DROPDOWNLIST,150,29,172,70
|
||||
CONTROL "Lineage II Versions",IDC_STATIC,"Button",WS_CHILD|WS_VISIBLE|BS_GROUPBOX,8,5,318,61
|
||||
CONTROL "Logging",IDC_STATIC,"Button",WS_CHILD|WS_VISIBLE|BS_GROUPBOX,178,116,148,70
|
||||
CONTROL "L2Walker_Drop_RequestGMList",IDC_C_L2WDROPGMLIST,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,16,132,146,11
|
||||
CONTROL "WarnUnknownPackets",IDC_C_WARNUNKP,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,184,171,88,11
|
||||
CONTROL "L2Walker_Fix_ChangeWaitType2",IDC_C_L2WSITFIX,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,16,155,146,11
|
||||
CONTROL "Force Game Server IP:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,124,219,76,9
|
||||
CONTROL "",IDC_E_FORCEGSIP,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,204,217,76,15,WS_EX_CLIENTEDGE
|
||||
CONTROL "",IDC_E_FORCEGSPORT,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL,290,217,32,15,WS_EX_CLIENTEDGE
|
||||
CONTROL ":",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,284,217,4,9
|
||||
CONTROL "L2Walker fixes",IDC_STATIC,"Button",WS_CHILD|WS_VISIBLE|BS_GROUPBOX,8,116,162,70
|
||||
CONTROL "L2Walker_Inject_StatusUpdate",IDC_C_L2WALKER_INJECTSTATUSUPDATE,"Button",WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,16,166,146,11
|
||||
CONTROL "Misc hacks (be careful!!!)",IDC_STATIC,"Button",WS_CHILD|WS_VISIBLE|BS_GROUPBOX,8,72,318,41
|
||||
CONTROL "Reply to L2J GameGuard query",IDC_C_GAMEGUARDREPLY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,16,97,134,11
|
||||
CONTROL "Gracia Epilogue Server protocol 148 -> Client protocol 146 hacks (experimental!)",IDC_C_EPILOGUE_148_146,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,18,46,302,11
|
||||
END
|
||||
|
||||
IDD_DEBUG DIALOGEX 0,0,266,158
|
||||
CAPTION "Debug"
|
||||
FONT 8,"MS Shell Dlg",400,0,1
|
||||
STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME|DS_SETFONT|DS_FIXEDSYS
|
||||
BEGIN
|
||||
CONTROL "Login listener status:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,7,7,68,8
|
||||
CONTROL "Game listener status:",IDC_STATIC,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP,7,25,69,8
|
||||
CONTROL "",IDC_ELLSTATUS,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_READONLY|ES_AUTOHSCROLL,90,7,40,14,WS_EX_CLIENTEDGE
|
||||
CONTROL "",IDC_EGLSTATUS,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_READONLY|ES_AUTOHSCROLL,89,23,40,14,WS_EX_CLIENTEDGE
|
||||
CONTROL "Start LL",IDC_STARTLL,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,141,7,50,14
|
||||
CONTROL "Start GL",IDC_STARTGL,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,142,23,50,14
|
||||
CONTROL "Stop LL",IDC_STOPLL,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,197,7,50,14
|
||||
CONTROL "Stop GL",IDC_STOPGL,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,198,23,50,14
|
||||
CONTROL "Flush Log File",IDC_FLUSH_LOG,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,7,42,50,14
|
||||
CONTROL "hp",IDC_HP,"Static",WS_VISIBLE|WS_GROUP|SS_SUNKEN|SS_LEFTNOWORDWRAP,7,61,72,11
|
||||
CONTROL "mp",IDC_MP,"Static",WS_VISIBLE|WS_GROUP|SS_SUNKEN|SS_LEFTNOWORDWRAP,82,61,72,11
|
||||
CONTROL "cp",IDC_CP,"Static",WS_VISIBLE|WS_GROUP|SS_SUNKEN|SS_LEFTNOWORDWRAP,156,61,72,11
|
||||
CONTROL "char_name",IDC_CHARNAME,"Static",WS_CHILD|WS_VISIBLE|WS_GROUP|SS_SUNKEN,7,76,251,11
|
||||
CONTROL "Enable Console",IDC_B_CONENABLE,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,65,42,64,14
|
||||
CONTROL "Disable Console",IDC_B_CONDISABLE,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,141,42,63,14
|
||||
CONTROL "Validate Interception",IDC_B_VALIDATEINTERCEPT,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,6,94,92,15
|
||||
CONTROL "Intercept connect",IDC_B_INTERCEPTCONNECT,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,106,94,80,15
|
||||
CONTROL "Check VP",IDC_B_CHECK_VIRTUALPROTECTEX,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,190,94,60,15
|
||||
CONTROL "Load L2Walker.dll",IDC_B_LOADWALKER,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,7,116,75,14
|
||||
CONTROL "Unload L2Walker.dll",IDC_B_UNLOADWALKER,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,90,116,76,15
|
||||
CONTROL "Dump All Relations",IDC_B_DUMP_ALL_RELATIONS,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,8,136,86,15
|
||||
CONTROL "Print address of UserAI::dwThreadID",IDC_B_PRINTADDRTID,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,102,136,136,15
|
||||
END
|
||||
|
||||
|
||||
6
l2detect/L2Detect_auth.h
Normal file
6
l2detect/L2Detect_auth.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_L2DETECT_AUTH
|
||||
#define H_L2DETECT_AUTH
|
||||
|
||||
extern "C" __declspec(dllimport) int getHWID( char *out );
|
||||
|
||||
#endif
|
||||
BIN
l2detect/L2Detect_auth.lib
Normal file
BIN
l2detect/L2Detect_auth.lib
Normal file
Binary file not shown.
122
l2detect/L2PacketTypes.cpp
Normal file
122
l2detect/L2PacketTypes.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "stdafx.h"
|
||||
#include "L2PacketTypes.h"
|
||||
#include "Logger.h"
|
||||
#include "ConfigIni.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
// constants are the same as in GameClient.h
|
||||
#define GCST_CONNECTED 1
|
||||
#define GCST_AUTHED 2
|
||||
#define GCST_IN_GAME 3
|
||||
|
||||
void L2PacketTypes_LogClient
|
||||
(
|
||||
L2_VERSION l2_version,
|
||||
int state,
|
||||
unsigned char ptype,
|
||||
unsigned short ptype2,
|
||||
unsigned short ptype3
|
||||
)
|
||||
{
|
||||
char pname[256];
|
||||
switch( state )
|
||||
{
|
||||
case GCST_CONNECTED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
case 0x0e: log_error( LOG_PACKETNAME, "Client: 0e ProtocolVersion\n" ); break;
|
||||
case 0x2b: log_error( LOG_PACKETNAME, "Client: 2b AuthLogin\n" ); break;
|
||||
default:
|
||||
{
|
||||
LOG_LEVEL log_level = LOG_PACKETNAME;
|
||||
if( g_cfg.WarnUnknownPacketsToStdout ) log_level = LOG_WARNING;
|
||||
log_error( log_level, "Client: Unknown packet %02X in state: CONNECTED\n", (unsigned int)ptype );
|
||||
} break;
|
||||
}
|
||||
} break; // CONNECTED
|
||||
|
||||
case GCST_AUTHED:
|
||||
{
|
||||
switch( ptype )
|
||||
{
|
||||
case 0x00: log_error( LOG_PACKETNAME, "Client: 00 LogoutRequest\n" ); break;
|
||||
case 0x12: log_error( LOG_PACKETNAME, "Client: 12 CharacterSelect\n" ); break;
|
||||
case 0x13: log_error( LOG_PACKETNAME, "Client: 13 NewCharacter\n" ); break;
|
||||
case 0x0c: log_error( LOG_PACKETNAME, "Client: 0c CharacterCreate\n" ); break;
|
||||
case 0xd0:
|
||||
{
|
||||
switch( ptype2 )
|
||||
{
|
||||
case 0x0036: log_error( LOG_PACKETNAME, "Client: D0:36 RequestGotoLobby (Final)\n" ); break;
|
||||
case 0x0039: log_error( LOG_PACKETNAME, "Client: D0:39 RequestGotoLobby\n" ); break;
|
||||
default:
|
||||
{
|
||||
LOG_LEVEL log_level = LOG_PACKETNAME;
|
||||
if( g_cfg.WarnUnknownPacketsToStdout ) log_level = LOG_WARNING;
|
||||
log_error( log_level, "Client: Unknown opcode2 %04X in state AUTHED for packet 0xD0\n", (unsigned int)ptype2 );
|
||||
} break;
|
||||
}
|
||||
} break; // double opcode packet
|
||||
default:
|
||||
{
|
||||
LOG_LEVEL log_level = LOG_PACKETNAME;
|
||||
if( g_cfg.WarnUnknownPacketsToStdout ) log_level = LOG_WARNING;
|
||||
log_error( log_level, "Client: Unknown packet %02X in state: AUTHED\n", (unsigned int)ptype );
|
||||
} break;
|
||||
}
|
||||
} break; // AUTHED
|
||||
|
||||
case GCST_IN_GAME:
|
||||
{
|
||||
L2Packets_GetL2PacketName( l2_version, false, ptype, ptype2, ptype3, pname, 255 );
|
||||
if( ptype == 0xd0 )
|
||||
{
|
||||
if( ptype2 == 0x51 )
|
||||
log_error( LOG_PACKETNAME, "Client: D0:51:%02X %s\n", ptype3, pname );
|
||||
else
|
||||
log_error( LOG_PACKETNAME, "Client: D0:%02X %s\n", ptype2, pname );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Client: %02X %s\n", ptype, pname );
|
||||
}
|
||||
} break; // IN_GAME
|
||||
|
||||
} // switch( state )
|
||||
}
|
||||
|
||||
void L2PacketTypes_LogServer
|
||||
(
|
||||
L2_VERSION l2_version,
|
||||
int state,
|
||||
unsigned char ptype,
|
||||
unsigned short ptype2,
|
||||
unsigned short ptype3
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ptype3);
|
||||
char pname[256];
|
||||
switch( state )
|
||||
{
|
||||
case GCST_CONNECTED:
|
||||
{
|
||||
} break;
|
||||
case GCST_AUTHED:
|
||||
{
|
||||
} break;
|
||||
case GCST_IN_GAME:
|
||||
{
|
||||
L2Packets_GetL2PacketName( l2_version, true, ptype, ptype2, ptype2, pname, 255 );
|
||||
if( ptype != 0xfe )
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Server: %02X %s\n", ptype, pname );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_PACKETNAME, "Server: FE:%02X %s\n", ptype2, pname );
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
23
l2detect/L2PacketTypes.h
Normal file
23
l2detect/L2PacketTypes.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef H_L2_PACKET_TYPES
|
||||
#define H_L2_PACKET_TYPES
|
||||
|
||||
|
||||
void L2PacketTypes_LogClient
|
||||
(
|
||||
L2_VERSION l2_version,
|
||||
int state,
|
||||
unsigned char ptype,
|
||||
unsigned short ptype2,
|
||||
unsigned short ptype3
|
||||
);
|
||||
|
||||
void L2PacketTypes_LogServer
|
||||
(
|
||||
L2_VERSION l2_version,
|
||||
int state,
|
||||
unsigned char ptype,
|
||||
unsigned short ptype2,
|
||||
unsigned short ptype3
|
||||
);
|
||||
|
||||
#endif
|
||||
170
l2detect/Logger.cpp
Normal file
170
l2detect/Logger.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
|
||||
extern CConfig g_cfg;
|
||||
// global ErrorLogger vars
|
||||
bool g_error_logger_enabled;
|
||||
bool g_error_logger_enabled_console;
|
||||
FILE *g_error_logger_file;
|
||||
bool g_error_logger_auto_prepend;
|
||||
CRITICAL_SECTION g_error_logger_cs;
|
||||
HANDLE g_error_logger_stdout;
|
||||
// strings
|
||||
char g_error_logger_strtype_unknown[16];
|
||||
char g_error_logger_strtype[LOG_LEVELS][16];
|
||||
|
||||
void ErrorLogger_InitStrings()
|
||||
{
|
||||
strcpy( g_error_logger_strtype_unknown, "[??] " );
|
||||
strcpy( g_error_logger_strtype[LOG_OK], "[++] " );
|
||||
strcpy( g_error_logger_strtype[LOG_ERROR], "[--] " );
|
||||
strcpy( g_error_logger_strtype[LOG_WARNING], "[WARN] " );
|
||||
strcpy( g_error_logger_strtype[LOG_USERAI], "[AI] " );
|
||||
strcpy( g_error_logger_strtype[LOG_PACKETNAME], "[PACK] " );
|
||||
strcpy( g_error_logger_strtype[LOG_DEBUG], "[DBG] " );
|
||||
strcpy( g_error_logger_strtype[LOG_DEBUGDUMP], "[DUMP] " );
|
||||
}
|
||||
|
||||
void ErrorLogger_Init()
|
||||
{
|
||||
g_error_logger_enabled = false;
|
||||
g_error_logger_enabled_console = false;
|
||||
g_error_logger_file = stdout;
|
||||
g_error_logger_auto_prepend = false;
|
||||
g_error_logger_stdout = INVALID_HANDLE_VALUE;
|
||||
InitializeCriticalSection( &g_error_logger_cs );
|
||||
ErrorLogger_InitStrings();
|
||||
}
|
||||
|
||||
void ErrorLogger_Enable( bool bEnable )
|
||||
{
|
||||
g_error_logger_enabled = bEnable;
|
||||
}
|
||||
|
||||
void ErrorLogger_EnableLoggingToConsole( bool bEnable )
|
||||
{
|
||||
EnterCriticalSection( &g_error_logger_cs );
|
||||
if( bEnable )
|
||||
{
|
||||
if( g_error_logger_enabled_console == false ) AllocConsole();
|
||||
g_error_logger_stdout = GetStdHandle( STD_OUTPUT_HANDLE );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_error_logger_stdout = INVALID_HANDLE_VALUE;
|
||||
if( g_error_logger_enabled_console == true ) FreeConsole();
|
||||
}
|
||||
g_error_logger_enabled_console = bEnable;
|
||||
LeaveCriticalSection( &g_error_logger_cs );
|
||||
}
|
||||
|
||||
void ErrorLogger_SetLogFile( FILE *f )
|
||||
{
|
||||
EnterCriticalSection( &g_error_logger_cs );
|
||||
if( !f ) g_error_logger_file = stdout; else g_error_logger_file = f;
|
||||
LeaveCriticalSection( &g_error_logger_cs );
|
||||
}
|
||||
|
||||
FILE *ErrorLogger_GetLogFile()
|
||||
{
|
||||
return g_error_logger_file;
|
||||
}
|
||||
|
||||
void ErrorLogger_FlushLogFile()
|
||||
{
|
||||
EnterCriticalSection( &g_error_logger_cs );
|
||||
if( g_error_logger_file ) fflush( g_error_logger_file );
|
||||
LeaveCriticalSection( &g_error_logger_cs );
|
||||
}
|
||||
|
||||
void ErrorLogger_SetAutoPrependErrorType( bool bPrepend )
|
||||
{
|
||||
g_error_logger_auto_prepend = bPrepend;
|
||||
}
|
||||
|
||||
int log_error( LOG_LEVEL logLevel, const char *_Format, ... )
|
||||
{
|
||||
if( !g_error_logger_enabled ) return 0;
|
||||
int ret = 0;
|
||||
if( (logLevel < 0) || (!_Format) ) return 0;
|
||||
if( logLevel > g_cfg.WarnMessageLevel ) return 0;
|
||||
EnterCriticalSection( &g_error_logger_cs );
|
||||
va_list l;
|
||||
va_start( l, _Format );
|
||||
if( g_error_logger_auto_prepend )
|
||||
{
|
||||
char *szPrepend = g_error_logger_strtype_unknown;
|
||||
if( (logLevel >= LOG_OK) && (logLevel <= LOGLEVEL_LAST) )
|
||||
szPrepend = g_error_logger_strtype[logLevel];
|
||||
fprintf( g_error_logger_file, "%s", szPrepend );
|
||||
// also write to console, if enabled
|
||||
if( g_error_logger_enabled_console )
|
||||
{
|
||||
DWORD numWritten = 0;
|
||||
WriteConsoleA( g_error_logger_stdout, szPrepend, (DWORD)strlen(szPrepend), &numWritten, NULL );
|
||||
}
|
||||
}
|
||||
ret = vfprintf( g_error_logger_file, _Format, l );
|
||||
// also write to console, if enabled
|
||||
if( g_error_logger_enabled_console && (ret > 0) )
|
||||
{
|
||||
char *cbuffer = (char *)malloc( ret+1 );
|
||||
if( cbuffer )
|
||||
{
|
||||
va_list l2;
|
||||
va_start( l2, _Format );
|
||||
vsprintf( cbuffer, _Format, l2 );
|
||||
DWORD numWritten = 0;
|
||||
WriteConsoleA( g_error_logger_stdout, cbuffer, (DWORD)strlen(cbuffer), &numWritten, NULL );
|
||||
free( cbuffer );
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection( &g_error_logger_cs );
|
||||
return ret;
|
||||
}
|
||||
|
||||
// forces NO prepend even if set to
|
||||
int log_error_np( LOG_LEVEL logLevel, const char *_Format, ... )
|
||||
{
|
||||
if( !g_error_logger_enabled ) return 0;
|
||||
int ret = 0;
|
||||
if( (logLevel < 0) || (!_Format) ) return 0;
|
||||
if( logLevel > g_cfg.WarnMessageLevel ) return 0;
|
||||
EnterCriticalSection( &g_error_logger_cs );
|
||||
va_list l;
|
||||
va_start( l, _Format );
|
||||
// no prepend, just vfprintf
|
||||
ret = vfprintf( g_error_logger_file, _Format, l );
|
||||
// also write to console, if enabled?
|
||||
if( g_error_logger_enabled_console && (ret > 0) )
|
||||
{
|
||||
char *cbuffer = (char *)malloc( ret+1 );
|
||||
if( cbuffer )
|
||||
{
|
||||
va_list l2;
|
||||
va_start( l2, _Format );
|
||||
vsprintf( cbuffer, _Format, l2 );
|
||||
DWORD numWritten = 0;
|
||||
WriteConsoleA( g_error_logger_stdout, cbuffer, (DWORD)strlen(cbuffer), &numWritten, NULL );
|
||||
free( cbuffer );
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection( &g_error_logger_cs );
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ErrorLogger_FormatLastError( char *msg, size_t nMaxCount, DWORD error_code )
|
||||
{
|
||||
FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, error_code, 0, msg, nMaxCount, NULL );
|
||||
}
|
||||
|
||||
void ErrorLogger_LogLastError( char *comment, DWORD error_code )
|
||||
{
|
||||
char errbuf[512];
|
||||
errbuf[0] = 0;
|
||||
ErrorLogger_FormatLastError( errbuf, 511, error_code );
|
||||
log_error( LOG_ERROR, "%s: error code: %u (%s)\n", comment, (unsigned int)error_code, errbuf );
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
33
l2detect/Logger.h
Normal file
33
l2detect/Logger.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef FL_ERRORLOGGER_H_
|
||||
#define FL_ERRORLOGGER_H_
|
||||
|
||||
typedef enum eLOG_LEVEL
|
||||
{
|
||||
LOG_OK = 0,
|
||||
LOG_ERROR, // 1
|
||||
LOG_WARNING, // 2
|
||||
LOG_USERAI, // 3
|
||||
LOG_PACKETNAME, // 4
|
||||
LOG_DEBUG, // 5
|
||||
LOG_DEBUGDUMP, // 6
|
||||
LOGLEVEL_LAST = LOG_DEBUGDUMP
|
||||
} LOG_LEVEL;
|
||||
|
||||
#define LOG_LEVELS 7
|
||||
|
||||
void ErrorLogger_Init();
|
||||
void ErrorLogger_Enable( bool bEnable );
|
||||
void ErrorLogger_EnableLoggingToConsole( bool bEnable );
|
||||
void ErrorLogger_SetLogFile( FILE *f );
|
||||
FILE *ErrorLogger_GetLogFile();
|
||||
void ErrorLogger_FlushLogFile();
|
||||
|
||||
void ErrorLogger_SetAutoPrependErrorType( bool bPrepend );
|
||||
|
||||
int log_error( LOG_LEVEL logLevel, const char *_Format, ... );
|
||||
int log_error_np( LOG_LEVEL logLevel, const char *_Format, ... ); // forces NO prepend even if set to
|
||||
|
||||
void ErrorLogger_FormatLastError( char *msg, size_t nMaxCount, DWORD error_code );
|
||||
void ErrorLogger_LogLastError( char *comment, DWORD error_code );
|
||||
|
||||
#endif /*FL_ERRORLOGGER_H_*/
|
||||
719
l2detect/LoginClient.cpp
Normal file
719
l2detect/LoginClient.cpp
Normal file
@@ -0,0 +1,719 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "LoginClient.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
/**
|
||||
* Function replaces IP and port of server with ID = serverID
|
||||
* in ServerList packet.
|
||||
* Usage:
|
||||
* unsigned char IP_new = {127,0,0,1};
|
||||
* int port_new = 7777;
|
||||
* unsigned int serverID = 1;
|
||||
* bool ret = FL_ReplaceServerIPPort( rawBytes, rawBytesLen, serverID, IP_new, port_new );
|
||||
*
|
||||
* returns true on success, false on error
|
||||
*/
|
||||
bool FL_ReplaceServerIPPort( unsigned char *b, unsigned int blen )
|
||||
{
|
||||
if( !b || (blen<26) ) return false;
|
||||
unsigned char fake_gsip[4] = {0,0,0,0};
|
||||
unsigned long lInetAddr = L2PNet_inet_addr( g_cfg.FakeListenGameIP );
|
||||
memcpy( (void *)&fake_gsip, (const void *)&lInetAddr, sizeof(lInetAddr) );
|
||||
unsigned short int sport = (unsigned short int)g_cfg.FakeListenGamePort;
|
||||
unsigned char cport[2] = {
|
||||
(unsigned char)( sport & 0x00FF),
|
||||
(unsigned char)((sport & 0xFF00) >> 8)
|
||||
};
|
||||
int gscount = (int)b[3];
|
||||
const int ServerList_Header_Size = 5;
|
||||
const int ServerList_OneServerInfo_Size = 21;
|
||||
int pos = ServerList_Header_Size; // pass packet header
|
||||
int i;
|
||||
//while( pos < (int)blen )
|
||||
log_error( LOG_DEBUG, "FL_ReplaceServerIPPort(): replacing IPs and ports for %d servers in list\n", gscount );
|
||||
for( i=0; i<gscount; i++ )
|
||||
{
|
||||
pos = ServerList_Header_Size + (i * ServerList_OneServerInfo_Size);
|
||||
//if( b[pos] == serverID )
|
||||
//{
|
||||
// found!
|
||||
//log_error( LOG_DEBUG, "FL_ReplaceServerIPPort(): found server ID %d at offset %d\n",
|
||||
// (int)serverID, pos );
|
||||
// b[pos] is ServerID
|
||||
// set new IP
|
||||
b[pos+1] = fake_gsip[0];
|
||||
b[pos+2] = fake_gsip[1];
|
||||
b[pos+3] = fake_gsip[2];
|
||||
b[pos+4] = fake_gsip[3];
|
||||
// set new port
|
||||
b[pos+5] = cport[0];
|
||||
b[pos+6] = cport[1];
|
||||
b[pos+7] = 0x00;
|
||||
b[pos+8] = 0x00;
|
||||
//return true;
|
||||
//}
|
||||
//else
|
||||
//pos += ServerList_OneServerInfo_Size; // go to next serverID...
|
||||
}
|
||||
//log_error( LOG_WARNING, "FL_ReplaceServerIPPort(): not found server ID %d",
|
||||
// (int)serverID );
|
||||
//return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FL_RecalculateChechksum(
|
||||
unsigned char *b,
|
||||
unsigned int blen )
|
||||
{
|
||||
if( !b || (blen<26) ) return false; // some error?
|
||||
L2LoginPacket lp;
|
||||
unsigned int newlen = 0;
|
||||
// set bytes, copy all except last 4 bytes - old checksum
|
||||
if( !lp.setBytes( b, blen-4 ) )
|
||||
{
|
||||
log_error( LOG_ERROR,
|
||||
"FL_RecalculateChechksum(): L2LoginPacket::setBytes( 0x%p, %u ) failed!\n",
|
||||
b, blen-4 );
|
||||
return false;
|
||||
}
|
||||
// append new checksum
|
||||
lp.appendChecksum( false ); // do not append 4 bytes
|
||||
// check resulting packet length - must be as original
|
||||
newlen = lp.getPacketSize();
|
||||
if( newlen == blen )
|
||||
{
|
||||
log_error( LOG_DEBUG, "FL_RecalculateChechksum(): newlen == blen, all OK\n" );
|
||||
memcpy( b, lp.getBytesPtr(), newlen );
|
||||
return true;
|
||||
}
|
||||
//else
|
||||
log_error( LOG_ERROR, "FL_RecalculateChechksum(): newlen (%u) != oldlen (%u)\n", newlen, blen );
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was only for debugging
|
||||
void GenerateFakePacket( L2Login_ServerList *p_sl )
|
||||
{
|
||||
if( !p_sl ) return;
|
||||
// ugly! but this packet is known sure to work!
|
||||
unsigned char b[] = {
|
||||
0x22, 0x00, // length
|
||||
0x04, 0x01, 0x01, // ptype, lastServer, nServers
|
||||
0x01, // serverID
|
||||
0x7F, 0x00, 0x00, 0x01, // serverIP
|
||||
0x61, 0x1E, 0x00, 0x00, // serverPort
|
||||
0x00, // age limit
|
||||
0x01, // is PvP
|
||||
0x00, 0x00, // current online
|
||||
0x0A, 0x00, // max online
|
||||
0x01, // is up
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, // flags...
|
||||
0xA5, 0x4A, 0xAA, 0xCE, // <-- WTF is here????
|
||||
0xB5, 0x54, 0xAA, 0xCE }; // here must be checksum
|
||||
p_sl->setBytes( b, sizeof(b) );
|
||||
}
|
||||
*/
|
||||
|
||||
LoginClient::LoginClient()
|
||||
{
|
||||
memset( sessionKey1, 0, sizeof(sessionKey1) );
|
||||
memset( sessionKey2, 0, sizeof(sessionKey2) );
|
||||
gsIP[0] = gsIP[1] = gsIP[2] = gsIP[3] = 0;
|
||||
gsPort = 0;
|
||||
g_login_client = this;
|
||||
state = LCST_OFFLINE;
|
||||
}
|
||||
|
||||
LoginClient::~LoginClient()
|
||||
{
|
||||
g_login_client = NULL;
|
||||
memset( sessionKey1, 0, sizeof(sessionKey1) );
|
||||
memset( sessionKey2, 0, sizeof(sessionKey2) );
|
||||
gsIP[0] = gsIP[1] = gsIP[2] = gsIP[3] = 0;
|
||||
gsPort = 0;
|
||||
state = LCST_OFFLINE;
|
||||
}
|
||||
|
||||
bool LoginClient::getSessionKeys( unsigned char *sKey1, unsigned char *sKey2 )
|
||||
{
|
||||
if( !sKey1 || !sKey2 ) return false;
|
||||
memcpy( sKey1, this->sessionKey1, 8 );
|
||||
memcpy( sKey2, this->sessionKey2, 8 );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoginClient::getPlayServerAddress( unsigned char *ip, unsigned short int *port )
|
||||
{
|
||||
if( !ip || !port ) return false;
|
||||
memcpy( ip, this->gsIP, sizeof(this->gsIP) );
|
||||
(*port) = this->gsPort;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoginClient::ProcessClient( SOCKET scl )
|
||||
{
|
||||
bool retVal = false;
|
||||
state = LCST_OFFLINE;
|
||||
|
||||
// connect to real login server
|
||||
log_error( LOG_DEBUG, "Establishing redirecting connection to %s:%d ",
|
||||
g_cfg.RealLoginServerIP, g_cfg.RealLoginServerPort );
|
||||
|
||||
SOCKET sr = L2PNet_TCPsocket_create( true );
|
||||
if( sr == INVALID_SOCKET )
|
||||
{
|
||||
log_error_np( LOG_ERROR, "\n" );
|
||||
log_error( LOG_ERROR, "ProcessClient(): cannot create socket!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
L2PNet_connect( sr, g_cfg.RealLoginServerIP, (unsigned short)g_cfg.RealLoginServerPort );
|
||||
int nTries = 20;
|
||||
int r = 0;
|
||||
while( nTries > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, "." );
|
||||
r = L2PNet_select( sr, L2PNET_SELECT_WRITE, 20000, NULL, NULL );
|
||||
if( r == 1 ) break;
|
||||
nTries--;
|
||||
}
|
||||
|
||||
if( r == 1 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, " Connected. Tries left: %d\n", nTries );
|
||||
state = LCST_CONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = LCST_OFFLINE;
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sr );
|
||||
L2PNet_closesocket( sr );
|
||||
log_error_np( LOG_DEBUG, " Not connected.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
this->postNotify( LCN_STATECHANGE, 1 ); // connected
|
||||
|
||||
// TODO: Login server session vars
|
||||
// login server session vars
|
||||
unsigned char ls_sessionID[4] = {0,0,0,0};
|
||||
unsigned int ls_sessionIDUInt = 0;
|
||||
unsigned int ls_protoVer = 0;
|
||||
unsigned char ls_RSA_pubKeyMod[128];
|
||||
unsigned char ls_ggShit[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
unsigned char ls_newBFKey[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
unsigned int ls_ggAuthResponse = 0;
|
||||
unsigned char ls_sessionKey1[8] = {0,0,0,0, 0,0,0,0};
|
||||
unsigned char ls_sessionKey2[8] = {0,0,0,0, 0,0,0,0};
|
||||
unsigned char ls_nGameServersCount = 0;
|
||||
unsigned char ls_lastServerID = 0; // last server ID
|
||||
unsigned char myGameServerIP[4] = {0,0,0,0};
|
||||
//char sMyGSIP[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
unsigned short int myGameServerPort = 0;
|
||||
int ls_chosenGameServer = -1;
|
||||
// login server session vars memset
|
||||
memset( ls_RSA_pubKeyMod, 0, sizeof(ls_RSA_pubKeyMod) );
|
||||
|
||||
// network vars
|
||||
int netTimeout = 30;
|
||||
int i = 0;
|
||||
unsigned char ptype = 0; // packet type byte
|
||||
unsigned char *rraw = NULL; // raw packet bytes
|
||||
unsigned int rcvdLen = 0;
|
||||
unsigned int sentLen = 0;
|
||||
|
||||
// packet objects
|
||||
L2LoginPacket *pack = NULL;
|
||||
L2Login_Init *p_init = NULL;
|
||||
//L2Login_RequestGGAuth *p_rgga = NULL;
|
||||
L2Login_GGAuthResponse *p_ggar = NULL;
|
||||
L2Login_LoginOK *p_lok = NULL;
|
||||
//L2Login_LoginFail *p_lfail = NULL;
|
||||
L2Login_ServerList *p_sl = NULL;
|
||||
L2Login_RequestServerLogin *p_rgsl = NULL;
|
||||
L2Login_PlayOK *p_pok = NULL;
|
||||
//L2Login_PlayFail *p_pfail = NULL;
|
||||
|
||||
// ServerInfo struct
|
||||
struct L2GameServerInfo gsi;
|
||||
memset( &gsi, 0, sizeof(gsi) );
|
||||
struct L2GameServerInfo gameservers_info[32];
|
||||
memset( gameservers_info, 0, sizeof(gameservers_info) );
|
||||
|
||||
// debug file
|
||||
//FILE *f = NULL;
|
||||
|
||||
// Init: receive Init packet from real login server
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( sr, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of Init packet from server.\n", rcvdLen );
|
||||
// resend it to client
|
||||
sentLen = 0;
|
||||
L2PacketSend2( rraw, scl, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of Init packet to client.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
|
||||
// decode and parse server's Init packet
|
||||
p_init = new L2Login_Init( rraw, rcvdLen );
|
||||
if( p_init->decodeBlowfish( true ) ) // true - Use Static BF Key
|
||||
{
|
||||
if( p_init->decodeXOR() )
|
||||
{
|
||||
// read packet data
|
||||
p_init->read_SessionID( ls_sessionID );
|
||||
memcpy( &ls_sessionIDUInt, ls_sessionID, sizeof(ls_sessionID) );
|
||||
ls_protoVer = p_init->read_ProtoVer();
|
||||
p_init->read_RSA_pubKeyMod( ls_RSA_pubKeyMod );
|
||||
p_init->read_GGShit( ls_ggShit );
|
||||
p_init->read_DynamicBFKey( ls_newBFKey );
|
||||
// printfs
|
||||
log_error( LOG_DEBUGDUMP, "SessionID: %02X %02X %02X %02X\n",
|
||||
ls_sessionID[0], ls_sessionID[1], ls_sessionID[2], ls_sessionID[3] );
|
||||
log_error( LOG_DEBUGDUMP, "Protocol ver: %08X\n", ls_protoVer );
|
||||
p_init->unscramble_RSA_PubKeyMod( ls_RSA_pubKeyMod );
|
||||
log_error( LOG_DEBUGDUMP, "Dynamic Blowfish key: " );
|
||||
i = 0;
|
||||
while( i < 16 ) log_error_np( LOG_DEBUGDUMP, "%02X ", ls_newBFKey[i++] );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
}
|
||||
else log_error( LOG_ERROR, "XOR decode failed\n" );
|
||||
}
|
||||
else log_error( LOG_ERROR, "BF decode failed\n" );
|
||||
delete p_init;
|
||||
p_init = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// RequestGGAuth
|
||||
// receive client's answer to server's Init packet. probably it is RequestGGAuth packet
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( scl, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of RequestGGAuth packet from client.\n", rcvdLen );
|
||||
// resend it to server
|
||||
sentLen = 0;
|
||||
L2PacketSend2( rraw, sr, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of RequestGGAuth packet to server.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
// try to decode and parse client's response
|
||||
//p_rgga = new L2Login_RequestGGAuth( rraw, rcvdLen );
|
||||
//p_rgga->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
//p_rgga->decodeBlowfish( false );
|
||||
//p_rgga->dumpToFile( stdout );
|
||||
//delete p_rgga;
|
||||
//p_rgga = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// GGAuthResponse
|
||||
// receive server's answer to client's RequstGGAuth packet
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( sr, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of GGAuthResponse packet from server.\n", rcvdLen );
|
||||
// resend it to client
|
||||
sentLen = 0;
|
||||
L2PacketSend2( rraw, scl, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of GGAuthResponse packet to client.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
p_ggar = new L2Login_GGAuthResponse( rraw, rcvdLen );
|
||||
//if( p_ggar ) printf( "GGAuthResponse object created\n" );
|
||||
//printf( "Setting bytes 0x%p %u len\n", rraw, rcvdLen );
|
||||
//if( p_ggar->setBytes( rraw, rcvdLen ) )
|
||||
// printf( "ProcessClient(): GGAuthResponse bytes set OK\n" );
|
||||
p_ggar->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
p_ggar->decodeBlowfish( false );
|
||||
ptype = p_ggar->getPacketType();
|
||||
if( ptype != 0x0B )
|
||||
log_error( LOG_WARNING, "Unknown GGAuthResponse code 0x%02X!!!!\n",
|
||||
(unsigned int)ptype );
|
||||
else
|
||||
log_error( LOG_OK, "GGAuthResponse: bypass GameGuard authorization...\n" );
|
||||
ls_ggAuthResponse = p_ggar->read_Response();
|
||||
if( ls_ggAuthResponse != ls_sessionIDUInt )
|
||||
{
|
||||
log_error( LOG_WARNING, "sessionID != ggAuthResponse (%04X != %04X)\n",
|
||||
ls_sessionIDUInt, ls_ggAuthResponse );
|
||||
}
|
||||
else log_error( LOG_DEBUG, "++++ SessionID == ggAuthResponse ++++\n" );
|
||||
delete p_ggar;
|
||||
p_ggar = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
state = LCST_AUTHED_GG;
|
||||
|
||||
// RequestAuthLogin
|
||||
// client must now attempt to login to server with its login and password
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( scl, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of RequestAuthLogin packet from client.\n", rcvdLen );
|
||||
// resend it to server
|
||||
sentLen = 0;
|
||||
//L2PacketSend( rraw, sr, netTimeout, 0, &sentLen );
|
||||
L2PacketSend2( rraw, sr, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of RequestAuthLogin packet to server.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
// display RequestAuthLogin contents
|
||||
//pack = new L2LoginPacket();
|
||||
//pack->setBytes( rraw, sentLen );
|
||||
//pack->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
//pack->decodeBlowfish( false );
|
||||
//pack->dumpToFile( stdout );
|
||||
//delete pack;
|
||||
//pack = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// LoginOK / LoginFail
|
||||
// Login server must now reply to RequestAuthLogin and tell us about result
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( sr, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of response to RequestAuthLogin from server.\n", rcvdLen );
|
||||
// resend it to client
|
||||
sentLen = 0;
|
||||
L2PacketSend2( rraw, scl, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of response to client.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "Server answer to RequestAuthLogin:\n" );
|
||||
pack = new L2LoginPacket( rraw, rcvdLen );
|
||||
pack->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
pack->decodeBlowfish( false );
|
||||
//pack->dumpToFile( stdout );
|
||||
ptype = pack->getPacketType();
|
||||
if( ptype == 0x03 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "++++ Login OK! ++++\n" );
|
||||
state = LCST_AUTHED_LOGIN;
|
||||
p_lok = new L2Login_LoginOK();
|
||||
p_lok->setBytes( pack->getBytesPtr(), pack->getPacketSize() );
|
||||
p_lok->read_sessionKey1( ls_sessionKey1 );
|
||||
delete p_lok;
|
||||
p_lok = NULL;
|
||||
log_error( LOG_DEBUGDUMP, "SessionKey1: " );
|
||||
for( i=0; i<sizeof(ls_sessionKey1); i++ )
|
||||
log_error_np( LOG_DEBUGDUMP, "%02X ", ls_sessionKey1[i] );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
}
|
||||
else if( ptype == 0x01 )
|
||||
{
|
||||
state = LCST_AUTH_ERROR;
|
||||
log_error( LOG_ERROR, "---- Login failed! (invalid user/pass? server offline?) ----\n" );
|
||||
goto l_netError;
|
||||
}
|
||||
else if( ptype == 0x02 )
|
||||
{
|
||||
state = LCST_AUTH_ERROR;
|
||||
log_error( LOG_ERROR, "---- Login failed! (account banned?)----\n" );
|
||||
goto l_netError;
|
||||
}
|
||||
else
|
||||
log_error( LOG_WARNING, "???? unknown reply to RequestAuthLogin: packet type: 0x%02X\n",
|
||||
(unsigned int)ptype );
|
||||
delete pack;
|
||||
pack = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// RequestServerList
|
||||
// after receiving packet LoginOK client displays license agreement
|
||||
// and after user clicks 'Agree' client sends RequestServerList packet
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( scl, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of RequestServerList packet from client.\n", rcvdLen );
|
||||
// resend it to server
|
||||
sentLen = 0;
|
||||
L2PacketSend2( rraw, sr, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of RequestServerList packet to server.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
// dump info about RequestServerList packet
|
||||
// [cut]
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// ServerList
|
||||
// login server now sends to client list of Game servers
|
||||
rcvdLen = 0;
|
||||
rraw = L2PacketReceive_malloc( sr, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of ServerList packet from server.\n", rcvdLen );
|
||||
// TODO: ServerList: NO, do not resend! :) modify it!!!
|
||||
// resend it to client
|
||||
/*sentLen = 0;
|
||||
L2PacketSend( rraw, scl, 5, 0, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of ServerList packet to client.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }*/
|
||||
|
||||
log_error( LOG_DEBUG, "ServerList packet:\n" );
|
||||
p_sl = new L2Login_ServerList();
|
||||
p_sl->setBytes( rraw, rcvdLen );
|
||||
// out RAW
|
||||
//printf( "RAW ServerList packet:\n" );
|
||||
//p_sl->dumpToFile( stdout );
|
||||
p_sl->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
p_sl->decodeBlowfish( false );
|
||||
// out BF decoded
|
||||
//printf( "BF Decoded ServerList packet:\n" );
|
||||
//p_sl->dumpToFile( stdout );
|
||||
// save to file :)
|
||||
//f = fopen( "ServerList.txt", "wt" );
|
||||
//if( f ) p_sl->dumpToFile( f );
|
||||
//fclose( f );
|
||||
// parse
|
||||
ptype = p_sl->getPacketType();
|
||||
if( ptype == 0x04 ) log_error( LOG_DEBUG, "++++ ServerList ++++\n" );
|
||||
p_sl->read_header( &ls_nGameServersCount, &ls_lastServerID );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
log_error( LOG_DEBUGDUMP, "ServerList: %d game servers, last server: %d\n",
|
||||
(int)ls_nGameServersCount, (int)ls_lastServerID );
|
||||
for( i=0; i<ls_nGameServersCount; i++ )
|
||||
{
|
||||
memset( &gsi, 0, sizeof(gsi) );
|
||||
if( p_sl->read_next_GS_Info( &gsi ) )
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "*** Server %d Info ***\n", i );
|
||||
log_error( LOG_DEBUGDUMP, "*** Server ID: %d\n", (int)gsi.gsID );
|
||||
log_error( LOG_DEBUGDUMP, "*** Server addr: %d.%d.%d.%d:%d\n",
|
||||
(int)gsi.gsIP[0],
|
||||
(int)gsi.gsIP[1],
|
||||
(int)gsi.gsIP[2],
|
||||
(int)gsi.gsIP[3],
|
||||
(int)gsi.gsPort );
|
||||
log_error( LOG_DEBUGDUMP, "*** Online: %d / %d (up: %d)\n", (int)gsi.gsPlayersOnline,
|
||||
(int)gsi.gsPlayersMax, (int)gsi.gsIsUp );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
// save this gameserver in array
|
||||
memcpy( (&gameservers_info[i]), &gsi, sizeof(L2GameServerInfo) );
|
||||
// is this GS chosen to play on? // ignore
|
||||
/*if( ((int)gsi.gsID) == g_cfg.PlayGameServerNo )
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "^^^^ we play here! ^^^^\n\n" );
|
||||
memcpy( myGameServerIP, gsi.gsIP, 4 );
|
||||
myGameServerPort = gsi.gsPort;
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "p_sl->read_next_GS_Info( &gsi ) failed!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
// replace server IP and port to what we need to intercept GS connection
|
||||
if( FL_ReplaceServerIPPort(
|
||||
(unsigned char *)p_sl->getBytesPtr(),
|
||||
p_sl->getPacketSize() ) )
|
||||
{
|
||||
log_error( LOG_DEBUG, "[++++] OK: ServerList packet modified\n" );
|
||||
// packet modified, we must update checksum in it
|
||||
if( FL_RecalculateChechksum(
|
||||
(unsigned char *)p_sl->getBytesPtr(),
|
||||
p_sl->getPacketSize() ) )
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "[++++] OK: ServerList packet checksum recalculated\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "ServerList packet checksum recalculate error!\n" );
|
||||
}
|
||||
}
|
||||
else log_error( LOG_ERROR, "ServerList packet modify error\n" );
|
||||
//GenerateFakePacket( p_sl ); // was called for debug only
|
||||
|
||||
//printf( "================\n" );
|
||||
//printf( "[I] ServerList packet after replacing its IP & port:\n" );
|
||||
//p_sl->dumpToFile( stdout );
|
||||
//printf( "=================\n" );
|
||||
|
||||
// encode modified packet again
|
||||
p_sl->encodeBlowfish( false );
|
||||
// out encoded
|
||||
//printf( "BF Encoded ServerList packet:\n" );
|
||||
//p_sl->dumpToFile( stdout );
|
||||
//rcvdLen = p_sl->getPacketSize();
|
||||
// resend it to client
|
||||
log_error( LOG_DEBUG, "Now resend %u bytes of ServerList to client...\n", rcvdLen );
|
||||
sentLen = 0;
|
||||
//L2PacketSend( p_sl->getBytesPtr(), scl, netTimeout, 0, &sentLen );
|
||||
L2PacketSend2( p_sl->getBytesPtr(), scl, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of ServerList packet to client.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
delete p_sl;
|
||||
p_sl = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// RequestServerLogin
|
||||
// client now must request server login
|
||||
rcvdLen = 0;
|
||||
//rraw = L2PacketReceive( scl, netTimeout, 0, &rcvdLen );
|
||||
rraw = L2PacketReceive_malloc( scl, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of RequestServerLogin packet from client.\n", rcvdLen );
|
||||
// resend it to server
|
||||
sentLen = 0;
|
||||
//L2PacketSend( rraw, sr, netTimeout, 0, &sentLen );
|
||||
L2PacketSend2( rraw, sr, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of RequestServerLogin packet to server.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
// dump info about RequestServerLogin packet
|
||||
p_rgsl = new L2Login_RequestServerLogin( rraw, rcvdLen );
|
||||
p_rgsl->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
p_rgsl->decodeBlowfish( false );
|
||||
// out
|
||||
//pack->dumpToFile( stdout );
|
||||
ptype = p_rgsl->getPacketType();
|
||||
if( ptype == 0x02 ) log_error( LOG_DEBUG, "++++ RequestServerLogin ++++\n" );
|
||||
p_rgsl->readInt(); p_rgsl->readInt(); // pass sessionKey1
|
||||
ls_chosenGameServer = (int)p_rgsl->read_GameServerID();
|
||||
log_error( LOG_DEBUG, "[INFO]: Client chooses to play on gameserver %d\n", ls_chosenGameServer );
|
||||
delete p_rgsl;
|
||||
p_rgsl = NULL;
|
||||
// free raw pack buffer
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// copy info about chosen game server
|
||||
if( (ls_chosenGameServer>=1) && (ls_chosenGameServer<=255) )
|
||||
{
|
||||
for( i=0; i<(int)ls_nGameServersCount; i++ )
|
||||
{
|
||||
if( gameservers_info[i].gsID == ls_chosenGameServer )
|
||||
{
|
||||
memcpy( &(myGameServerIP), &(gameservers_info[i].gsIP), 4 );
|
||||
myGameServerPort = gameservers_info[i].gsPort;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//g_cfg.PlayGameServerNo = ls_chosenGameServer; // PlayGameServerNo removed from config
|
||||
log_error( LOG_DEBUG, "we play on GS #%d: %d.%d.%d.%d:%d\n",
|
||||
ls_chosenGameServer,
|
||||
(int)myGameServerIP[0], (int)myGameServerIP[1], (int)myGameServerIP[2], (int)myGameServerIP[3],
|
||||
myGameServerPort );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "Client choosed GS ID %d, which is INVALID! must be [1..255]\n", ls_chosenGameServer );
|
||||
}
|
||||
|
||||
// PlayOK / PlayFail
|
||||
// login server now sends to client if client can play o selected server
|
||||
rcvdLen = 0;
|
||||
//rraw = L2PacketReceive( sr, netTimeout, 0, &rcvdLen );
|
||||
rraw = L2PacketReceive_malloc( sr, netTimeout*1000, &rcvdLen );
|
||||
if( !rraw ) { log_error( LOG_ERROR, "receive failed!\n" ); goto l_netError; }
|
||||
log_error( LOG_DEBUG, "ProcessClient(): rcvd %u bytes of response to RequestServerLogin packet from server.\n", rcvdLen );
|
||||
// resend it to client
|
||||
sentLen = 0;
|
||||
L2PacketSend2( rraw, scl, netTimeout*1000, &sentLen );
|
||||
log_error( LOG_DEBUG, "ProcessClient(): resent %u bytes of response to RequestServerLogin packet to client.\n", sentLen );
|
||||
if( sentLen != rcvdLen ) { log_error( LOG_ERROR, "rcvd != sent! (%u != %u)\n", rcvdLen, sentLen ); goto l_netError; }
|
||||
pack = new L2LoginPacket();
|
||||
pack->setBytes( rraw, sentLen );
|
||||
pack->setDynamicBFKey( ls_newBFKey, 16 );
|
||||
pack->decodeBlowfish( false );
|
||||
// out...
|
||||
//printf( "\nResponse to RequestServerLogin:\n" );
|
||||
//pack->dumpToFile( stdout );
|
||||
// parse result
|
||||
ptype = pack->getPacketType();
|
||||
if( ptype == 0x06 ) // PlayFail
|
||||
{
|
||||
log_error( LOG_ERROR, "---- PlayFail! ----\n" );
|
||||
goto l_netError;
|
||||
}
|
||||
else if( ptype == 0x07 ) // PlayOK!
|
||||
{
|
||||
log_error( LOG_DEBUG, "++++ PlayOK! ++++\n" );
|
||||
p_pok = new L2Login_PlayOK();
|
||||
p_pok->setBytes( pack->getBytesPtr(), pack->getPacketSize() );
|
||||
p_pok->read_sessionKey2( ls_sessionKey2 );
|
||||
delete p_pok;
|
||||
p_pok = NULL;
|
||||
log_error( LOG_DEBUGDUMP, "SessionKey#2: " );
|
||||
for( i=0; i<8; i++ ) log_error_np( LOG_DEBUGDUMP, "%02X ", ls_sessionKey2[i] );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "=====================================\n" );
|
||||
log_error( LOG_ERROR, "???? Unknown packet type 0x%02X! ????\n",
|
||||
(unsigned int)ptype );
|
||||
pack->dumpToFile( stdout );
|
||||
log_error( LOG_ERROR, "=====================================\n" );
|
||||
goto l_netError;
|
||||
}
|
||||
// delete...
|
||||
delete pack;
|
||||
pack = NULL;
|
||||
// free raw packet data
|
||||
free( rraw );
|
||||
rraw = NULL;
|
||||
|
||||
// mark as connected OK
|
||||
retVal = true;
|
||||
|
||||
goto l_closeSockets; // jump over netError handler
|
||||
l_netError:
|
||||
log_error( LOG_ERROR, "ProcessClient(): some network error :\\\n" );
|
||||
if( rraw ) free( rraw );
|
||||
rraw = NULL;
|
||||
retVal = false; // mark as connection failed
|
||||
l_closeSockets:
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sr );
|
||||
L2PNet_closesocket( sr );
|
||||
state = LCST_OFFLINE;
|
||||
|
||||
// save data
|
||||
memcpy( this->sessionKey1, ls_sessionKey1, sizeof(ls_sessionKey1) );
|
||||
memcpy( this->sessionKey2, ls_sessionKey2, sizeof(ls_sessionKey2) );
|
||||
this->gsPort = myGameServerPort;
|
||||
memcpy( this->gsIP, myGameServerIP, sizeof(myGameServerIP) );
|
||||
|
||||
// notify radar window about disconnection
|
||||
this->postNotify( LCN_STATECHANGE, 0 ); // disconnected
|
||||
|
||||
log_error( LOG_DEBUG, "ProcessClient(): ended client processing. Returning %d\n",
|
||||
(int)retVal );
|
||||
|
||||
// return indicator
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
void LoginClient::setNotifyWindow( HWND notifyHwnd, UINT notifyMsg )
|
||||
{
|
||||
this->hWndNotify = notifyHwnd;
|
||||
this->uMsgNotify = notifyMsg;
|
||||
}
|
||||
|
||||
extern HWND g_radardll_hwnd;
|
||||
|
||||
void LoginClient::postNotify( WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
//if( hWndNotify == NULL || (uMsgNotify < WM_USER) ) return;
|
||||
//PostMessage( hWndNotify, uMsgNotify, wParam, lParam );
|
||||
PostMessage( g_radardll_hwnd, (WM_USER+106), wParam, lParam );
|
||||
}
|
||||
|
||||
LoginClient *g_login_client = NULL;
|
||||
43
l2detect/LoginClient.h
Normal file
43
l2detect/LoginClient.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef FAKELOGIN_LOGINCLIENT_H_
|
||||
#define FAKELOGIN_LOGINCLIENT_H_
|
||||
|
||||
// client state
|
||||
#define LCST_OFFLINE 0 // not connected to LS :)
|
||||
#define LCST_CONNECTED 1 // just connected to LS
|
||||
#define LCST_AUTHED_GG 2 // passed GG auth
|
||||
#define LCST_AUTHED_LOGIN 3 // authorized
|
||||
#define LCST_AUTH_ERROR 4 // auth error
|
||||
|
||||
// window notification wParam
|
||||
#define LCN_STATECHANGE 1 // lParam will hold new state
|
||||
|
||||
class LoginClient
|
||||
{
|
||||
public:
|
||||
LoginClient();
|
||||
virtual ~LoginClient();
|
||||
public:
|
||||
bool ProcessClient( SOCKET scl );
|
||||
bool getSessionKeys( unsigned char *sKey1, unsigned char *sKey2 );
|
||||
bool getPlayServerAddress( unsigned char *ip, unsigned short int *port );
|
||||
public:
|
||||
void setNotifyWindow( HWND notifyHwnd, UINT notifyMsg );
|
||||
void postNotify( WPARAM wParam, LPARAM lParam );
|
||||
public:
|
||||
int getState() { return state; }
|
||||
protected:
|
||||
int state;
|
||||
protected:
|
||||
unsigned char sessionKey1[8];
|
||||
unsigned char sessionKey2[8];
|
||||
unsigned char gsIP[4];
|
||||
unsigned short int gsPort;
|
||||
protected:
|
||||
// notify window
|
||||
HWND hWndNotify;
|
||||
UINT uMsgNotify;
|
||||
};
|
||||
|
||||
extern LoginClient *g_login_client;
|
||||
|
||||
#endif /*FAKELOGIN_LOGINCLIENT_H_*/
|
||||
275
l2detect/LoginListener.cpp
Normal file
275
l2detect/LoginListener.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "LoginListener.h"
|
||||
#include "LoginClient.h"
|
||||
#include "GameListener.h"
|
||||
|
||||
extern class CConfig g_cfg; // declared in main.cpp
|
||||
extern class GameListener *g_pgame; // declared in main.cpp
|
||||
extern HWND g_radardll_hwnd; // declared in RadarDllWnd.cpp
|
||||
|
||||
struct FLLT_INFO
|
||||
{
|
||||
class LoginListener *cls;
|
||||
};
|
||||
|
||||
void FLS_Thread_freeInfo( struct FLLT_INFO *pinfo )
|
||||
{
|
||||
if( pinfo->cls->m_listen_socket != INVALID_SOCKET )
|
||||
{
|
||||
L2PNet_shutdown( pinfo->cls->m_listen_socket );
|
||||
L2PNet_closesocket( pinfo->cls->m_listen_socket );
|
||||
pinfo->cls->m_listen_socket = INVALID_SOCKET;
|
||||
}
|
||||
if( pinfo->cls->m_hThread ) CloseHandle( pinfo->cls->m_hThread );
|
||||
pinfo->cls->m_hThread = NULL;
|
||||
pinfo->cls->m_signal = 0;
|
||||
free( pinfo );
|
||||
log_error( LOG_DEBUG, "FLS_Thread(): thread info struct freed\n" );
|
||||
}
|
||||
|
||||
DWORD WINAPI LoginListener::FLS_Thread( LPVOID lpParam )
|
||||
{
|
||||
struct FLLT_INFO *pinfo = (struct FLLT_INFO *)lpParam;
|
||||
lpParam = NULL;
|
||||
if( !pinfo )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): lpParam is NULL! Exit\n" );
|
||||
return 0;
|
||||
}
|
||||
class LoginListener *cls = pinfo->cls;
|
||||
if( !cls )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): pinfo->cls is NULL! Exit\n" );
|
||||
FLS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
cls->m_listen_socket = INVALID_SOCKET;
|
||||
//DWORD wait_res = 0;
|
||||
//SOCKET s = sock_tcp_create();
|
||||
SOCKET s = L2PNet_TCPsocket_create( true );
|
||||
if( s == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): socket create failed!\n" );
|
||||
FLS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mb_yes = 0;
|
||||
int bind_fail = 0;
|
||||
ll_bind:
|
||||
bind_fail = L2PNet_bind( s, g_cfg.FakeListenLoginIP, (unsigned short)g_cfg.FakeListenLoginPort );
|
||||
if( bind_fail )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): socket bind at %s:%d failed\n",
|
||||
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
||||
int wsaerr = L2PNet_WSAGetLastError();
|
||||
if( wsaerr == WSAEADDRINUSE )
|
||||
{
|
||||
wchar_t errmsg[256];
|
||||
wsprintfW( errmsg, L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD> %S:%d <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!\n"
|
||||
L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD>?",
|
||||
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
||||
mb_yes = MessageBoxW( g_radardll_hwnd, errmsg, L"L2Detect: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!", MB_ICONSTOP | MB_YESNO );
|
||||
if( mb_yes == IDYES ) goto ll_bind;
|
||||
}
|
||||
FLS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( L2PNet_listen( s ) )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): listen() failed\n" );
|
||||
FLS_Thread_freeInfo( pinfo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
cls->m_listen_socket = s;
|
||||
|
||||
log_error( LOG_DEBUG, "FLS_Thread(): started, listening at %s:%d\n",
|
||||
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
||||
|
||||
// raise thread priority
|
||||
if( !SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL ) )
|
||||
log_error( LOG_WARNING, "FLS_Thread(): raise thread priority failed!\n" );
|
||||
|
||||
int r = 0;
|
||||
char clientIP[32] = {0};
|
||||
unsigned short clientPort = 0;
|
||||
SOCKET scl = INVALID_SOCKET;
|
||||
int rdyR = 0, rdyW = 0; // ready to recv/send
|
||||
unsigned int scode = 0; // signal to thread
|
||||
int should_exit = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
should_exit = 0;
|
||||
//r = sock_tcp_wait_ready_to_recv( s, 0, 500000 );
|
||||
rdyR = 0;
|
||||
r = L2PNet_select( s, L2PNET_SELECT_READ, 500, &rdyR, &rdyW );
|
||||
scode = cls->getLastSignal();
|
||||
if( scode == FLLS_STOP )
|
||||
{
|
||||
log_error( LOG_DEBUG, "FLS_Thread(): exit signal\n" );
|
||||
should_exit = 1;
|
||||
}
|
||||
if( should_exit ) break; // break while()
|
||||
if( r == -1 )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): socket select() error\n" );
|
||||
break;
|
||||
}
|
||||
if( r == 1 && rdyR )
|
||||
{
|
||||
//log_error( LOG_DEBUG, "FLS_Thread(): Somebody connected? :)\n" );
|
||||
clientIP[0] = 0;
|
||||
clientPort = 0;
|
||||
scl = INVALID_SOCKET;
|
||||
//scl = sock_tcp_accept( s, clientIP, &clientPort );
|
||||
scl = L2PNet_accept( s, clientIP, &clientPort );
|
||||
if( scl == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): accept() failed...\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
//log_error( LOG_DEBUG, "FLS_Thread(): accepted client %s:%d\n", clientIP, clientPort );
|
||||
log_error( LOG_OK, "LoginListener: accepted client %s:%d\n", clientIP, clientPort );
|
||||
LoginClient lc;
|
||||
if( lc.ProcessClient( scl ) )
|
||||
{
|
||||
unsigned char sKey1[8] = {0,0,0,0, 0,0,0,0};
|
||||
unsigned char sKey2[8] = {0,0,0,0, 0,0,0,0};
|
||||
struct PlayServerInfo sinfo;
|
||||
lc.getSessionKeys( sKey1, sKey2 );
|
||||
lc.getPlayServerAddress( sinfo.ip, &(sinfo.port) );
|
||||
|
||||
// ONLY IN OUTGAME MODE stop listener after successful client acception
|
||||
if( g_cfg.isInGameMode == false )
|
||||
{
|
||||
// stop listener after successful client acception
|
||||
log_error( LOG_DEBUG, "FLS_Thread(): LoginListener stopping self in outgame mode, "
|
||||
"after client accepted, freeing port %s:%d\n",
|
||||
g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort );
|
||||
//cls->signalStop();
|
||||
should_exit = 1;
|
||||
}
|
||||
|
||||
if( !g_pgame )
|
||||
{
|
||||
log_error( LOG_ERROR, "FLS_Thread(): Game listener is NULL????" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// set play server info to game listener
|
||||
g_pgame->setPlayServerInfo( &sinfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
} // somebody connected?
|
||||
if( should_exit ) break; // break while()
|
||||
} // while(1)
|
||||
|
||||
//sock_tcp_close_shutdown( s, SD_BOTH );
|
||||
// network sockets clenup done by FLS_Thread_freeInfo()
|
||||
|
||||
FLS_Thread_freeInfo( pinfo );
|
||||
log_error( LOG_DEBUG, "FLS_Thread() ended\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// class
|
||||
|
||||
|
||||
LoginListener::LoginListener()
|
||||
{
|
||||
this->_initNull();
|
||||
}
|
||||
|
||||
LoginListener::~LoginListener()
|
||||
{
|
||||
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
||||
this->_initNull();
|
||||
}
|
||||
|
||||
|
||||
bool LoginListener::start()
|
||||
{
|
||||
// cleanup ?
|
||||
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
||||
this->_initNull();
|
||||
// alloc thread info struct
|
||||
struct FLLT_INFO *pinfo = (struct FLLT_INFO *)malloc( sizeof( struct FLLT_INFO ) );
|
||||
if( !pinfo ) return false;
|
||||
// fill info
|
||||
pinfo->cls = this;
|
||||
// create thread object
|
||||
this->m_hThread = NULL;
|
||||
DWORD dwTID = 0;
|
||||
this->m_hThread = (HANDLE)_beginthreadex(
|
||||
NULL, // security
|
||||
0, // stack size
|
||||
(unsigned int (__stdcall*)(void *))FLS_Thread, // thread function
|
||||
(void *)pinfo, // thread function argument - lpParam
|
||||
0, // flags
|
||||
(unsigned int *)(&dwTID) );
|
||||
if( !this->m_hThread )
|
||||
{
|
||||
free( pinfo );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoginListener::waitStopped( unsigned int timeoutMsec )
|
||||
{
|
||||
if( !this->m_hThread ) return true;
|
||||
DWORD wait_res = WaitForSingleObject( this->m_hThread, (DWORD)timeoutMsec );
|
||||
if( wait_res != WAIT_OBJECT_0 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "LoginListener::waitStopped(): WaitForSingleObject() returned 0x%08X\n", wait_res );
|
||||
if( wait_res == WAIT_TIMEOUT ) log_error( LOG_DEBUG, "LoginListener::waitStopped(): WAIT_TIMEOUT\n" );
|
||||
return false;
|
||||
}
|
||||
// wait OK, close kernel objects
|
||||
if( this->m_hThread ) CloseHandle( this->m_hThread );
|
||||
// initialize self
|
||||
this->_initNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoginListener::terminateThread()
|
||||
{
|
||||
if( this->m_hThread )
|
||||
{
|
||||
TerminateThread( this->m_hThread, 0xBAADF00D );
|
||||
CloseHandle( this->m_hThread );
|
||||
this->m_hThread = NULL;
|
||||
this->m_signal = 0;
|
||||
// thread resources
|
||||
if( m_listen_socket != INVALID_SOCKET )
|
||||
{
|
||||
//sock_tcp_close_shutdown( m_listen_socket, SD_BOTH );
|
||||
L2PNet_shutdown( m_listen_socket );
|
||||
L2PNet_closesocket( m_listen_socket );
|
||||
}
|
||||
m_listen_socket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
void LoginListener::_initNull()
|
||||
{
|
||||
m_hThread = NULL;
|
||||
m_signal = 0;
|
||||
// thread resources
|
||||
m_listen_socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
bool LoginListener::isRunning() const
|
||||
{
|
||||
if( this->m_hThread != NULL ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
34
l2detect/LoginListener.h
Normal file
34
l2detect/LoginListener.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef FAKELOGINLISTENER_H_
|
||||
#define FAKELOGINLISTENER_H_
|
||||
|
||||
// signals to thread
|
||||
#define FLLS_STOP 1
|
||||
|
||||
class LoginListener
|
||||
{
|
||||
friend void FLS_Thread_freeInfo( struct FLLT_INFO *pinfo );
|
||||
protected:
|
||||
static DWORD WINAPI FLS_Thread( LPVOID lpParam );
|
||||
public:
|
||||
LoginListener();
|
||||
virtual ~LoginListener();
|
||||
public:
|
||||
bool start();
|
||||
void signal( unsigned int code ) { this->m_signal = code; }
|
||||
void signalStop() { this->signal( FLLS_STOP ); }
|
||||
bool waitStopped( unsigned int timeoutMsec );
|
||||
unsigned int getLastSignal() const { return this->m_signal; }
|
||||
void setLastSignal( unsigned int code ) { this->m_signal = code; }
|
||||
void terminateThread();
|
||||
public:
|
||||
bool isRunning() const;
|
||||
protected:
|
||||
void _initNull();
|
||||
protected:
|
||||
HANDLE m_hThread;
|
||||
unsigned int m_signal;
|
||||
// thread resources
|
||||
SOCKET m_listen_socket;
|
||||
};
|
||||
|
||||
#endif /*FAKELOGINLISTENER_H_*/
|
||||
204
l2detect/NpcArray.cpp
Normal file
204
l2detect/NpcArray.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#include "stdafx.h"
|
||||
#include "NpcArray.h"
|
||||
#include "Logger.h"
|
||||
#include "WorldObjectTree.h"
|
||||
#include "RadarDllWnd.h"
|
||||
|
||||
L2Npc *npc_array[NPCA_MAX_NPCS];
|
||||
CRITICAL_SECTION cs_npc_array;
|
||||
|
||||
//HWND npcArray_updateHWND;
|
||||
//UINT npcArray_updateMSG;
|
||||
|
||||
// forward
|
||||
//void NpcArray_PostUpdateMessage();
|
||||
|
||||
void NpcArray_Init()
|
||||
{
|
||||
//npcArray_updateHWND = NULL;
|
||||
//npcArray_updateMSG = 0;
|
||||
InitializeCriticalSection( &cs_npc_array );
|
||||
int i;
|
||||
for( i=0; i<NPCA_MAX_NPCS; i++ ) npc_array[i] = new L2Npc();
|
||||
}
|
||||
|
||||
void NpcArray_Free()
|
||||
{
|
||||
NpcArray_Lock();
|
||||
int i;
|
||||
for( i=0; i<NPCA_MAX_NPCS; i++ )
|
||||
{
|
||||
if( npc_array[i] != NULL )
|
||||
{
|
||||
delete npc_array[i];
|
||||
npc_array[i] = NULL;
|
||||
}
|
||||
}
|
||||
NpcArray_Unlock();
|
||||
DeleteCriticalSection( &cs_npc_array );
|
||||
}
|
||||
|
||||
void NpcArray_AddNpcInfo( L2Npc *pNpcInfo )
|
||||
{
|
||||
NpcArray_Lock();
|
||||
int idx = -1;
|
||||
L2OBJECT_TYPE type;
|
||||
/*BOOL bRet = */WorldObjectTree_GetInfoByObjectID( pNpcInfo->objectID, &type, &idx );
|
||||
//
|
||||
if( (idx == -1) || (type != L2OT_NPC) )
|
||||
{
|
||||
// Add new npc info
|
||||
idx = NpcArray_FindFreeIndex();
|
||||
if( idx == -1 )
|
||||
{
|
||||
NpcArray_Unlock();
|
||||
return;
|
||||
}
|
||||
if( !npc_array[idx] ) npc_array[idx] = new L2Npc();
|
||||
if( !npc_array[idx] )
|
||||
{
|
||||
NpcArray_Unlock();
|
||||
return;
|
||||
}
|
||||
memcpy( npc_array[idx], pNpcInfo, sizeof(class L2Npc) );
|
||||
//log_error( LOG_OK, "NpcArray: Added new[%d]: [%S] [%S] (%d,%d,%d) tpml %u, oid %u\n",
|
||||
// idx, name, title, x,y,z, templateID, objectID );
|
||||
// add to WorldObjectTree
|
||||
WorldObjectTree_AddObject( pNpcInfo->objectID, L2OT_NPC, idx );
|
||||
// add to radar window
|
||||
RadarWnd_AddNpc( pNpcInfo->objectID );
|
||||
}
|
||||
else if( (idx>=0) && (idx<NPCA_MAX_NPCS) && (type==L2OT_NPC) )
|
||||
{
|
||||
// update info on existing NPC
|
||||
if( !npc_array[idx] )
|
||||
{
|
||||
// try to allocate!
|
||||
npc_array[idx] = new L2Npc();
|
||||
if( !npc_array[idx] )
|
||||
{
|
||||
NpcArray_Unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy( npc_array[idx], pNpcInfo, sizeof(class L2Npc) );
|
||||
//log_error( LOG_OK, "NpcArray: Updated[%d]: [%S] [%S] (%d,%d,%d) tpml %u, oid %u\n",
|
||||
// idx, name, title, x,y,z, templateID, objectID );
|
||||
RadarWnd_UpdNpc( npc_array[idx]->objectID );
|
||||
}
|
||||
NpcArray_Unlock();
|
||||
}
|
||||
|
||||
void NpcArray_DelNPC( unsigned int objectID )
|
||||
{
|
||||
NpcArray_Lock();
|
||||
int idx = NpcArray_FindNPCByObjectID( objectID );
|
||||
if( idx == -1 )
|
||||
{
|
||||
NpcArray_Unlock();
|
||||
return;
|
||||
}
|
||||
if( npc_array[idx] )
|
||||
{
|
||||
npc_array[idx]->setUnused();
|
||||
}
|
||||
//log_error( LOG_OK, "NpcArray: deleted " );
|
||||
// delete also from world object tree
|
||||
WorldObjectTree_DelObject( objectID );
|
||||
NpcArray_Unlock();
|
||||
// del from radar window
|
||||
RadarWnd_DelNpc( objectID );
|
||||
}
|
||||
|
||||
void NpcArray_DelNPCByIdx( int idx )
|
||||
{
|
||||
if( idx<0 || (idx>=NPCA_MAX_NPCS) ) return;
|
||||
NpcArray_Lock();
|
||||
if( npc_array[idx] )
|
||||
{
|
||||
unsigned int objectID = npc_array[idx]->objectID;
|
||||
npc_array[idx]->setUnused();
|
||||
//log_error( LOG_OK, "NpcArray: deleted npc %u from index OK\n", objectID, idx );
|
||||
// delete from world object tree
|
||||
WorldObjectTree_DelObject( objectID );
|
||||
// del from radar window
|
||||
RadarWnd_DelNpc( objectID );
|
||||
}
|
||||
NpcArray_Unlock();
|
||||
}
|
||||
|
||||
void NpcArray_Lock()
|
||||
{
|
||||
EnterCriticalSection( &cs_npc_array );
|
||||
}
|
||||
|
||||
void NpcArray_Unlock()
|
||||
{
|
||||
LeaveCriticalSection( &cs_npc_array );
|
||||
}
|
||||
|
||||
int NpcArray_FindNPCByObjectID( unsigned int objectID )
|
||||
{
|
||||
int ret = -1;
|
||||
int i;
|
||||
NpcArray_Lock();
|
||||
for( i=0; i<NPCA_MAX_NPCS; i++ )
|
||||
{
|
||||
if( npc_array[i] == NULL ) continue;
|
||||
if( npc_array[i]->objectID == objectID )
|
||||
{
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NpcArray_Unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NpcArray_FindFreeIndex()
|
||||
{
|
||||
int i;
|
||||
NpcArray_Lock();
|
||||
for( i=0; i<NPCA_MAX_NPCS; i++ )
|
||||
{
|
||||
if( npc_array[i] == NULL )
|
||||
{
|
||||
npc_array[i] = new L2Npc(); // allocate new
|
||||
npc_array[i]->setUnused(); // and set as unused
|
||||
NpcArray_Unlock();
|
||||
return i;
|
||||
}
|
||||
if( npc_array[i]->isUnused() )
|
||||
{
|
||||
NpcArray_Unlock();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
NpcArray_Unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//void NpcArray_SetUpdateCommand( HWND hWnd, UINT uMsg )
|
||||
//{
|
||||
// npcArray_updateHWND = hWnd;
|
||||
// npcArray_updateMSG = uMsg;
|
||||
//}
|
||||
|
||||
//void NpcArray_PostUpdateMessage()
|
||||
//{
|
||||
// if( !npcArray_updateHWND ) return;
|
||||
// if( npcArray_updateMSG < WM_USER ) return;
|
||||
// PostMessage( npcArray_updateHWND, npcArray_updateMSG, 0, 0 );
|
||||
//}
|
||||
|
||||
void NpcArray_DeleteAll()
|
||||
{
|
||||
NpcArray_Lock();
|
||||
int i;
|
||||
for( i=0; i<NPCA_MAX_NPCS; i++ )
|
||||
{
|
||||
if( npc_array[i] ) npc_array[i]->setUnused();
|
||||
}
|
||||
//npcArray_count = 0;
|
||||
NpcArray_Unlock();
|
||||
}
|
||||
24
l2detect/NpcArray.h
Normal file
24
l2detect/NpcArray.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef H_NPC_ARRAY
|
||||
#define H_NPC_ARRAY
|
||||
|
||||
#define NPCA_MAX_NPCS 512
|
||||
|
||||
extern L2Npc *npc_array[NPCA_MAX_NPCS];
|
||||
|
||||
void NpcArray_Init();
|
||||
void NpcArray_Free();
|
||||
void NpcArray_DeleteAll();
|
||||
|
||||
void NpcArray_AddNpcInfo( L2Npc *pNpcInfo );
|
||||
void NpcArray_DelNPC( unsigned int objectID );
|
||||
void NpcArray_DelNPCByIdx( int idx );
|
||||
|
||||
void NpcArray_Lock();
|
||||
void NpcArray_Unlock();
|
||||
|
||||
int NpcArray_FindNPCByObjectID( unsigned int objectID );
|
||||
int NpcArray_FindFreeIndex();
|
||||
|
||||
//void NpcArray_SetUpdateCommand( HWND hWnd, UINT uMsg );
|
||||
|
||||
#endif
|
||||
347
l2detect/PacketInjector.cpp
Normal file
347
l2detect/PacketInjector.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
#include "stdafx.h"
|
||||
#include "GameClient.h"
|
||||
#include "PacketInjector.h"
|
||||
#include "Logger.h"
|
||||
#include "ConfigIni.h"
|
||||
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
extern class CConfig g_cfg; // in main.cpp
|
||||
|
||||
void PGen_Action( unsigned int oid, int x, int y, int z, unsigned char useShift )
|
||||
{
|
||||
if( !g_game_client ) return;
|
||||
L2Game_Action p;
|
||||
p.create( oid, x, y, z, useShift );
|
||||
unsigned char bytes[32];
|
||||
memcpy( bytes, p.getBytesPtr(), p.getPacketSize() );
|
||||
g_game_client->InjectPacketToServer( bytes, p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_AttackRequest( unsigned int oid, int x, int y, int z, unsigned char useShift )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x01 ); // AttackRequest
|
||||
p.writeUInt( oid );
|
||||
p.writeInt( x );
|
||||
p.writeInt( y );
|
||||
p.writeInt( z );
|
||||
p.writeUChar( useShift );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_UseItem( unsigned int oid )
|
||||
{
|
||||
if( !g_game_client ) return;
|
||||
L2Game_UseItem p;
|
||||
p.create( oid );
|
||||
unsigned char bytes[32];
|
||||
memcpy( bytes, p.getBytesPtr(), p.getPacketSize() );
|
||||
g_game_client->InjectPacketToServer( bytes, p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestJoinParty( const wchar_t *invitePlayer, unsigned int lootRules )
|
||||
{
|
||||
if( !g_game_client ) return;
|
||||
L2Game_RequestJoinParty p;
|
||||
p.create( invitePlayer, lootRules );
|
||||
g_game_client->InjectPacketToServer( const_cast<unsigned char *>(p.getBytesPtr()), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestOustPartyMember( const wchar_t *dismissPlayer )
|
||||
{
|
||||
if( !dismissPlayer ) return;
|
||||
L2GamePacket p;
|
||||
p.writeReset();
|
||||
p.writeUChar( 0x45 );
|
||||
p.writeUnicodeString( dismissPlayer );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_GameGuardReply_L2J()
|
||||
{
|
||||
L2GamePacket pack;
|
||||
pack.setPacketType( 0xCB ); // GameGuardReply
|
||||
pack.writeUInt( 0x78F0977F );
|
||||
pack.writeUInt( 0xD6E63C04 );
|
||||
pack.writeUInt( 0x89F60C71 );
|
||||
pack.writeUInt( 0x70069EDD );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)pack.getBytesPtr(), pack.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestTargetCanceld( bool abortCast )
|
||||
{
|
||||
L2GamePacket pack;
|
||||
pack.setPacketType( 0x48 ); // RequestTargetCanceld
|
||||
pack.writeH( abortCast ? 0x00 : 0x01 ); // abort cast or cancel target
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)pack.getBytesPtr(), pack.getPacketSize(), true );
|
||||
}
|
||||
|
||||
/* public final static int ALL = 0;
|
||||
public final static int SHOUT = 1; //!
|
||||
public final static int TELL = 2;
|
||||
public final static int PARTY = 3; //#
|
||||
public final static int CLAN = 4; //@
|
||||
public final static int GM = 5;
|
||||
public final static int PETITION_PLAYER = 6; // used for petition
|
||||
public final static int PETITION_GM = 7; //* used for petition
|
||||
public final static int TRADE = 8; //+
|
||||
public final static int ALLIANCE = 9; //$
|
||||
public final static int ANNOUNCEMENT = 10;
|
||||
public final static int PARTYROOM_ALL = 16; //(Red)
|
||||
public final static int PARTYROOM_COMMANDER = 15; //(Yellow)
|
||||
public final static int HERO_VOICE = 17;
|
||||
public final static int BATTLEFIELD = 20; */
|
||||
void PGen_Say2C( unsigned int channelID, const wchar_t *text, const wchar_t *player_to /*= NULL*/ )
|
||||
{
|
||||
L2GamePacket pack;
|
||||
pack.setPacketType( 0x49 ); // Say2
|
||||
pack.writeS( text ); // <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
pack.writeD( channelID ); // <20><><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> = <20><>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( (channelID == 2 /*TELL*/) && player_to ) pack.writeS( player_to );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)pack.getBytesPtr(), pack.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_MoveBackwardToLocation( int dst_x, int dst_y, int dst_z, int src_x, int src_y, int src_z )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x0F ); // MoveBackwardToLocation
|
||||
p.writeD( dst_x );
|
||||
p.writeD( dst_y );
|
||||
p.writeD( dst_z );
|
||||
p.writeD( src_x );
|
||||
p.writeD( src_y );
|
||||
p.writeD( src_z );
|
||||
p.writeD( 0x01 ); // 0x01 = for movement was used mouse
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestBypassToserver( const wchar_t *bypassStr )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x23 ); // RequestBypassToServer
|
||||
p.writeS( bypassStr );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestLinkHtml( const wchar_t *link )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x22 ); // RequestLinkHtml
|
||||
p.writeS( link );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestActionUse( unsigned int actionId, bool ctrlPressed, bool shiftPressed )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x56 ); // RequestActionUse
|
||||
p.writeUInt( actionId );
|
||||
p.writeUInt( ctrlPressed ? 0x01 : 0x00 );
|
||||
p.writeC( shiftPressed ? 0x01 : 0x00 );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestAutoSoulshot( unsigned int itemID, bool enable )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0xD0 );
|
||||
p.writeUShort( 0x000D ); // D0:000D RequestAutoSoulshot
|
||||
p.writeUInt( itemID );
|
||||
enable ? p.writeUInt( 1 ) : p.writeUInt( 0 );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
/** Client: Len 13 [RequestDispel]
|
||||
0D 00
|
||||
D0 4E 00 // D0:004E RequestDispel D0:004B RequestExDspel (G.Final)
|
||||
4B 05 00 00 // skillID 1355 (PoWater?)
|
||||
01 00 00 00 // skillLvl lvl 1 **/
|
||||
void PGen_RequestDispel( unsigned int skillID )
|
||||
{
|
||||
// only since Gracia T2
|
||||
if( g_cfg.L2_version < (int)L2_VERSION_T2 ) return;
|
||||
UserBuff buf;
|
||||
g_game_client->ai.buffs.getBuffnfoBySkillId( skillID, &buf );
|
||||
if( (buf.skillID == 0) || (buf.skillLvl == 0) ) return; // error, no such buff!
|
||||
// create packet
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0xD0 );
|
||||
// opcode is different in Gracia Final
|
||||
if( g_cfg.L2_version <= (int)L2_VERSION_T22 )
|
||||
p.writeUShort( 0x004E ); // D0:004E RequestDispel L2 <= T22
|
||||
else
|
||||
p.writeUShort( 0x004B ); // D0:004B RequestDispel L2 >= T23 Gracia Final
|
||||
p.writeUInt( skillID );
|
||||
p.writeUInt( buf.skillLvl );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestMagicSkillUse( unsigned int skillID, unsigned int ctrlPressed, unsigned char shiftPressed )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x39 ); // RequestMagicSkillUse
|
||||
p.writeUInt( skillID );
|
||||
p.writeUInt( ctrlPressed );
|
||||
p.writeUChar( shiftPressed );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestWithdrawalParty()
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x44 ); // RequestWithDrawalParty
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
void PGen_RequestChangePartyLeader( const wchar_t *playerName )
|
||||
{
|
||||
if( !playerName ) return;
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0xD0 ); // D0:000C RequestChangePartyLeader
|
||||
p.writeUShort( 0x0000C );
|
||||
p.writeUnicodeString( playerName );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)p.getBytesPtr(), p.getPacketSize(), true );
|
||||
}
|
||||
|
||||
// hack function, do not use!
|
||||
// input: string consisting of sequence of hex chars, representing packet, starting from packet type
|
||||
// packet length will be prefixed automatically!
|
||||
// example: 1F39A400109ACB00003D2BFFFFA9F3FFFF00 - 1F Action packet, without packet len
|
||||
void PGen_send_hackPacketHex_toServer( const char *szHexStr )
|
||||
{
|
||||
if( !szHexStr ) return;
|
||||
int ll = (int)strlen( szHexStr );
|
||||
if( ll % 2 ) return;
|
||||
int nBytes = ll / 2;
|
||||
int i;
|
||||
unsigned char *bytebuffer = (unsigned char *)malloc( nBytes );
|
||||
if( !bytebuffer ) return;
|
||||
memset( bytebuffer, 0, nBytes );
|
||||
//log_error_np( LOG_OK, "\ngame_sendPacketHex(): %d bytes\n", nBytes );
|
||||
for( i=0; i<ll; i+=2 )
|
||||
{
|
||||
char c1 = szHexStr[i];
|
||||
char c2 = szHexStr[i+1];
|
||||
//log_error_np( LOG_OK, "Parsing byte [%d] %c%c... ", i/2, c1, c2 );
|
||||
int i1 = 0;
|
||||
int i2 = 0;
|
||||
if( (c1>='0') && (c1<='9') ) i1 = 0 + c1 - '0';
|
||||
if( (c1>='a') && (c1<='f') ) i1 = 10 + c1 - 'a';
|
||||
if( (c1>='A') && (c1<='F') ) i1 = 10 + c1 - 'A';
|
||||
if( (c2>='0') && (c2<='9') ) i2 = 0 + c2 - '0';
|
||||
if( (c2>='a') && (c2<='f') ) i2 = 10 + c2 - 'a';
|
||||
if( (c2>='A') && (c2<='F') ) i2 = 10 + c2 - 'A';
|
||||
//log_error_np( LOG_OK, "%d * 16 + %d... ", i1, i2 );
|
||||
unsigned char b = (unsigned char)( ((i1 << 4) | i2) & 0xFF );
|
||||
//log_error_np( LOG_OK, "%d (%02X)\n", (int)b, b );
|
||||
bytebuffer[i/2] = b;
|
||||
}
|
||||
L2GamePacket *pack = new L2GamePacket();
|
||||
pack->writeReset();
|
||||
pack->writeBytes( bytebuffer, nBytes );
|
||||
g_game_client->InjectPacketToServer( (unsigned char *)pack->getBytesPtr(), pack->getPacketSize(), true );
|
||||
delete pack;
|
||||
pack = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void PGenC_NpcHtmlMessage( unsigned int npcObjectId, const wchar_t *text, unsigned int itemId )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x19 ); // NpcHtmlMessage
|
||||
p.writeD( npcObjectId );
|
||||
p.writeS( text );
|
||||
p.writeD( itemId );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
}
|
||||
|
||||
void PGenC_DeleteObject( unsigned int objectID )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x08 ); // DeleteObject
|
||||
p.writeUInt( objectID );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
}
|
||||
|
||||
void PGenC_MoveToLocation( unsigned int objectID, int x, int y, int z, int dx, int dy, int dz )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x2f ); // MoveToLocation
|
||||
p.writeUInt( objectID );
|
||||
p.writeD( dx );
|
||||
p.writeD( dy );
|
||||
p.writeD( dz );
|
||||
p.writeD( x );
|
||||
p.writeD( y );
|
||||
p.writeD( z );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
}
|
||||
|
||||
void PGenC_StopMove( unsigned int objectID, int x, int y, int z, unsigned int heading )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x47 ); // StopMove
|
||||
p.writeUInt( objectID );
|
||||
p.writeD( x );
|
||||
p.writeD( y );
|
||||
p.writeD( z );
|
||||
p.writeUInt( heading );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
}
|
||||
|
||||
void PGenC_CreatureSay( unsigned int objectID, unsigned int channelID, const wchar_t *senderName, const wchar_t *text )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0x4A ); // CreatureSay
|
||||
p.writeD( objectID ); // objectID
|
||||
p.writeD( channelID ); // channelID (15 - Commander, 17 - Hero)
|
||||
p.writeS( senderName ); // sender name
|
||||
p.writeS( text ); // text
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
}
|
||||
|
||||
void PGenC_StatusUpdate( L2Player *pl )
|
||||
{
|
||||
L2GamePacket p;
|
||||
// first send info about curHp/maxHp
|
||||
p.setPacketType( 0x18 ); // StatusUpdate
|
||||
p.writeUInt( pl->objectID );
|
||||
p.writeUInt( 2 ); // number of attributes
|
||||
// cur HP
|
||||
p.writeUInt( 0x09 );
|
||||
p.writeUInt( (unsigned int)pl->curHp );
|
||||
// max HP
|
||||
p.writeUInt( 0x0A );
|
||||
p.writeUInt( (unsigned int)pl->maxHp );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
|
||||
// then send info about curMp/maxMp
|
||||
p.setPacketType( 0x18 ); // StatusUpdate
|
||||
p.writeUInt( pl->objectID );
|
||||
p.writeUInt( 2 ); // number of attributes
|
||||
// cur MP
|
||||
p.writeUInt( 0x0B );
|
||||
p.writeUInt( (unsigned int)pl->curHp );
|
||||
// max MP
|
||||
p.writeUInt( 0x0C );
|
||||
p.writeUInt( (unsigned int)pl->maxHp );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
//log_error( LOG_USERAI, "Injected StatusUpdate about [%S]\n", pl->charName );
|
||||
}
|
||||
|
||||
void PGenC_ShowMiniMap( unsigned int mapID /*= 1665*/ )
|
||||
{
|
||||
L2GamePacket p;
|
||||
p.setPacketType( 0xA3 ); // ShowMiniMap
|
||||
p.writeUInt( mapID );
|
||||
g_game_client->InjectPacketToClient( (unsigned char *)p.getBytesPtr(), p.getPacketSize() );
|
||||
}
|
||||
35
l2detect/PacketInjector.h
Normal file
35
l2detect/PacketInjector.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef H_PGEN
|
||||
#define H_PGEN
|
||||
|
||||
// to server
|
||||
void PGen_Action( unsigned int oid, int x, int y, int z, unsigned char useShift );
|
||||
void PGen_AttackRequest( unsigned int oid, int x, int y, int z, unsigned char useShift );
|
||||
void PGen_GameGuardReply_L2J();
|
||||
void PGen_MoveBackwardToLocation( int dst_x, int dst_y, int dst_z, int src_x, int src_y, int src_z );
|
||||
void PGen_RequestActionUse( unsigned int actionId, bool ctrlPressed, bool shiftPressed );
|
||||
void PGen_RequestAutoSoulshot( unsigned int itemID, bool enable );
|
||||
void PGen_RequestBypassToserver( const wchar_t *bypassStr );
|
||||
void PGen_RequestChangePartyLeader( const wchar_t *playerName );
|
||||
void PGen_RequestDispel( unsigned int skillID );
|
||||
void PGen_RequestJoinParty( const wchar_t *invitePlayer, unsigned int lootRules );
|
||||
void PGen_RequestLinkHtml( const wchar_t *link );
|
||||
void PGen_RequestMagicSkillUse( unsigned int skillID, unsigned int ctrlPressed, unsigned char shiftPressed );
|
||||
void PGen_RequestOustPartyMember( const wchar_t *dismissPlayer );
|
||||
void PGen_RequestTargetCanceld( bool abortCast );
|
||||
void PGen_RequestWithdrawalParty();
|
||||
void PGen_Say2C( unsigned int channelID, const wchar_t *text, const wchar_t *player_to = NULL );
|
||||
void PGen_UseItem( unsigned int oid );
|
||||
|
||||
// to client
|
||||
void PGenC_CreatureSay( unsigned int objectID, unsigned int channelID, const wchar_t *senderName, const wchar_t *text );
|
||||
void PGenC_DeleteObject( unsigned int objectID );
|
||||
void PGenC_MoveToLocation( unsigned int objectID, int x, int y, int z, int dx, int dy, int dz );
|
||||
void PGenC_NpcHtmlMessage( unsigned int npcObjectId, const wchar_t *text, unsigned int itemId = 0 );
|
||||
void PGenC_StatusUpdate( L2Player *pl );
|
||||
void PGenC_StopMove( unsigned int objectID, int x, int y, int z, unsigned int heading );
|
||||
void PGenC_ShowMiniMap( unsigned int mapID = 1665 );
|
||||
|
||||
// hack!..
|
||||
void PGen_send_hackPacketHex_toServer( const char *szHexStr );
|
||||
|
||||
#endif
|
||||
7
l2detect/PostBuildEvent.cmd
Normal file
7
l2detect/PostBuildEvent.cmd
Normal file
@@ -0,0 +1,7 @@
|
||||
set out=..\..\out\dist_L2Detect
|
||||
|
||||
rem Copy DLL
|
||||
copy /y %2\%1.dll %2\%out%
|
||||
|
||||
rem Copy PDB
|
||||
rem copy /y %2\%1.pdb %2\%out%
|
||||
882
l2detect/ProtocolConverter.cpp
Normal file
882
l2detect/ProtocolConverter.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "ConfigIni.h"
|
||||
|
||||
#define PCODE_SELLLIST 0x06
|
||||
#define PCODE_BUYLIST 0x07
|
||||
#define PCODE_ITEMLIST 0x11
|
||||
#define PCODE_TRADESTART 0x14
|
||||
#define PCODE_TRADEOWNADD 0x1A
|
||||
#define PCODE_TRADEOTHERADD 0x1B
|
||||
#define PCODE_INVENTORYUPDATE 0x21
|
||||
#define PCODE_WAREHOUSEDEPOSITLIST 0x41
|
||||
#define PCODE_WAREHOUSEWITHDRAWLIST 0x42
|
||||
#define PCODE_PRIVATESTORELISTSELL 0xA1
|
||||
#define PCODE_PRIVATESTORELISTBUY 0xBE
|
||||
#define PCODE_RELATIONCHANGED 0xCE
|
||||
|
||||
#define PCODE2_EXBUYSELLLITSTPACKET 0x00B7
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
int pconv_was_Init = 0;
|
||||
int pconv_enabled = 0;
|
||||
int pconv_epilogue = 0;
|
||||
int pconv_table[256];
|
||||
|
||||
void ProtoConv_Init()
|
||||
{
|
||||
memset( pconv_table, 0, sizeof(pconv_table) );
|
||||
//
|
||||
pconv_table[ PCODE_SELLLIST ] = 1;
|
||||
pconv_table[ PCODE_BUYLIST ] = 1;
|
||||
pconv_table[ PCODE_ITEMLIST ] = 1;
|
||||
pconv_table[ PCODE_TRADESTART ] = 1;
|
||||
pconv_table[ PCODE_TRADEOWNADD ] = 1;
|
||||
pconv_table[ PCODE_TRADEOTHERADD ] = 1;
|
||||
pconv_table[ PCODE_INVENTORYUPDATE ] = 1;
|
||||
pconv_table[ PCODE_WAREHOUSEDEPOSITLIST ] = 1;
|
||||
pconv_table[ PCODE_WAREHOUSEWITHDRAWLIST ] = 1;
|
||||
pconv_table[ PCODE_PRIVATESTORELISTSELL ] = 1;
|
||||
pconv_table[ PCODE_PRIVATESTORELISTBUY ] = 1;
|
||||
pconv_table[ PCODE_RELATIONCHANGED ] = 1;
|
||||
//
|
||||
pconv_was_Init = 1;
|
||||
// disable protocol converter for Hellbound <=> Gracia
|
||||
// enable conversion only T1/Hellbound => Gracia
|
||||
//if( (g_cfg.L2_version <= L2_VERSION_T15) && (g_cfg.L2_client_version >= L2_VERSION_T2) )
|
||||
// pconv_enabled = 1;
|
||||
//if( (g_cfg.L2_version >= L2_VERSION_T2) && (g_cfg.L2_client_version <= L2_VERSION_T15) )
|
||||
// pconv_enabled = 1;
|
||||
// Gracia Epilogue Server:148 -> Client:146 protocol conversion
|
||||
if( (g_cfg.GraciaEpilogueProtocol_148_hacks) &&
|
||||
(g_cfg.OverrideGameProtocolVersion == 148) &&
|
||||
(g_cfg.L2_client_version == L2_VERSION_T24) &&
|
||||
(g_cfg.L2_version == L2_VERSION_T24) )
|
||||
{
|
||||
pconv_enabled = 1;
|
||||
pconv_epilogue = 1;
|
||||
}
|
||||
if( pconv_enabled )
|
||||
{
|
||||
log_error( LOG_USERAI, "Enabled protocol converter\n" );
|
||||
if( pconv_epilogue ) log_error( LOG_USERAI, "Protocol converter: Gracia Epilogue mode!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
int ProtoConv_IsEnabled()
|
||||
{
|
||||
if( !pconv_was_Init ) ProtoConv_Init();
|
||||
return pconv_enabled;
|
||||
}
|
||||
|
||||
int ProtoConv_ConvExistsForPacket( unsigned char pcode )
|
||||
{
|
||||
if( !pconv_was_Init ) ProtoConv_Init();
|
||||
return pconv_table[ pcode ];
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertItemList( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // ItemList old
|
||||
L2GamePacket iln; // ItemList new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType();
|
||||
iln.setPacketType( ptype ); // ptype must be == PCODE_ITEMLIST
|
||||
//
|
||||
int i = 0;
|
||||
unsigned short temp_short;
|
||||
unsigned int temp_int;
|
||||
unsigned int objectID;
|
||||
unsigned int itemID;
|
||||
unsigned int count; // count of one stackable ITEM slot
|
||||
unsigned long long int count64; // count of one stackable ITEM slot (for protocol >= Final)
|
||||
unsigned short icount; // count of all used items SLOTS in inventory
|
||||
//
|
||||
//writeH(_showWindow ? 0x01 : 0x00);
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//writeH(count);
|
||||
icount = ilo.readUShort();
|
||||
iln.writeUShort( icount );
|
||||
//
|
||||
for( i=0; i<(int)icount; i++ )
|
||||
{
|
||||
//writeH(temp.getItem().getType1()); // item type1
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//writeD(temp.getObjectId());
|
||||
objectID = ilo.readUInt();
|
||||
iln.writeUInt( objectID );
|
||||
//writeD(temp.getItemId());
|
||||
itemID = ilo.readUInt();
|
||||
iln.writeUInt( itemID );
|
||||
//writeD(temp.getLocationSlot()); // T1
|
||||
temp_int = ilo.readUInt();
|
||||
iln.writeUInt( temp_int );
|
||||
//writeD(temp.getCount());
|
||||
if( !pconv_epilogue )
|
||||
{
|
||||
count = ilo.readUInt();
|
||||
iln.writeUInt( count );
|
||||
}
|
||||
else
|
||||
{
|
||||
count64 = ilo.readUInt64();
|
||||
iln.writeUInt64( count64 );
|
||||
}
|
||||
//writeH(temp.getItem().getType2()); // item type2
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//writeH(temp.getCustomType1()); // item type3
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//writeH(temp.isEquipped() ? 0x01 : 0x00);
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//writeD(temp.getItem().getBodyPart());
|
||||
temp_int = ilo.readUInt();
|
||||
iln.writeUInt( temp_int );
|
||||
//writeH(temp.getEnchantLevel()); // enchant level
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//race tickets
|
||||
//writeH(temp.getCustomType2()); // item type3
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
// writeD(temp.getAugmentation().getAugmentationId());
|
||||
temp_int = ilo.readUInt();
|
||||
iln.writeUInt( temp_int );
|
||||
//writeD(temp.getMana());
|
||||
temp_int = ilo.readUInt();
|
||||
iln.writeUInt( temp_int );
|
||||
|
||||
// in gracia final elemental attributes are not Ds, they are Hs
|
||||
if( g_cfg.L2_version <= L2_VERSION_T22 )
|
||||
{
|
||||
// T1
|
||||
//writeD(temp.getAttackElementType());
|
||||
temp_int = ilo.readUInt();
|
||||
iln.writeUInt( temp_int );
|
||||
//writeD(temp.getAttackElementPower());
|
||||
temp_int = ilo.readUInt();
|
||||
iln.writeUInt( temp_int );
|
||||
int ia = 0;
|
||||
for( ia=0; ia<6; ia++)
|
||||
{
|
||||
// element def attr(i)
|
||||
temp_int = ilo.readUInt(); // 1
|
||||
iln.writeUInt( temp_int );
|
||||
}
|
||||
}
|
||||
else if( g_cfg.L2_version >= L2_VERSION_T23 )
|
||||
{
|
||||
//writeH(temp.getAttackElementType());
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
//writeH(temp.getAttackElementPower());
|
||||
temp_short = ilo.readUShort();
|
||||
iln.writeUShort( temp_short );
|
||||
int ia = 0;
|
||||
for( ia=0; ia<6; ia++)
|
||||
{
|
||||
// element def attr(i)
|
||||
temp_short = ilo.readUShort(); // 1
|
||||
iln.writeUShort( temp_short );
|
||||
}
|
||||
}
|
||||
|
||||
// isTimeLimitedItem() depends on version!!!!
|
||||
// read last 4 bytes for each item in inv only if server is >= T2
|
||||
temp_int = 0x00000000;
|
||||
if( g_cfg.L2_version >= L2_VERSION_T2 )
|
||||
{
|
||||
//writeD(0x00);
|
||||
temp_int = ilo.readUInt();
|
||||
}
|
||||
// write timeLimitedItem for each item in inv only if client is >= T2
|
||||
if( g_cfg.L2_client_version >= L2_VERSION_T2 )
|
||||
{
|
||||
iln.writeUInt( temp_int );
|
||||
}
|
||||
|
||||
// Gracia Epilogue has 3 Hs more
|
||||
if( pconv_epilogue )
|
||||
{
|
||||
// do NOT read 3 enchant effects from original ItemList
|
||||
// but don't write them to resulting ItemList
|
||||
iln.writeH( 0 ); // Enchant effect 1
|
||||
iln.writeH( 0 ); // Enchant effect 2
|
||||
iln.writeH( 0 ); // Enchant effect 3
|
||||
}
|
||||
}
|
||||
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_ItemList: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertInventoryUpdate( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // InventoryUpdate old
|
||||
L2GamePacket iln; // InventoryUpdate new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType();
|
||||
iln.setPacketType( ptype ); // ptype must be == PCODE_INVENTORYUPDATE
|
||||
//
|
||||
int count = ilo.readH(); iln.writeH( (short)count );
|
||||
// P.S. count <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = 1 <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
|
||||
int i, ie;
|
||||
//unsigned short h;
|
||||
//unsigned int d;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // update type
|
||||
iln.writeH( ilo.readH() ); // item type 1
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeD( ilo.readD() ); // item location slot
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // item type 2
|
||||
iln.writeH( ilo.readH() ); // item custom type 1 (always 0x00)
|
||||
iln.writeH( ilo.readH() ); // item is equipped
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeH( ilo.readH() ); // item enchant level
|
||||
iln.writeH( ilo.readH() ); // item custom type 2 (pet name related..?)
|
||||
iln.writeD( ilo.readD() ); // item aug id
|
||||
iln.writeD( ilo.readD() ); // item mana
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T2
|
||||
iln.writeD( ilo.readD() ); // item time
|
||||
// T24
|
||||
// write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_InventoryUpdate: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertBuyList( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // BuyList old
|
||||
L2GamePacket iln; // BuyList new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType();
|
||||
iln.setPacketType( ptype ); // ptype must be == PCODE_BUYLIST
|
||||
//
|
||||
iln.writeQ( ilo.readQ() ); // money
|
||||
iln.writeD( ilo.readD() ); // buylist ID
|
||||
int count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // item type 1
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // item type 2
|
||||
iln.writeH( ilo.readH() ); // item custom type 1 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeH( ilo.readH() ); // item enchant level
|
||||
iln.writeH( ilo.readH() ); // 0x00 ...
|
||||
iln.writeH( ilo.readH() ); // 0x00
|
||||
iln.writeQ( ilo.readQ() ); // price
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24
|
||||
// write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_BuyList: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertSellList( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // SellList old
|
||||
L2GamePacket iln; // SellList new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType();
|
||||
iln.setPacketType( ptype ); // ptype must be == PCODE_SELLLIST
|
||||
//
|
||||
iln.writeQ( ilo.readQ() ); // money
|
||||
iln.writeD( ilo.readD() ); // seller npcID
|
||||
int count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // item type 1
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // item type 2
|
||||
iln.writeH( ilo.readH() ); // item custom type 1 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeH( ilo.readH() ); // item enchant level
|
||||
iln.writeH( ilo.readH() ); // 0x00 ...
|
||||
iln.writeH( ilo.readH() ); // item custom type 2
|
||||
iln.writeQ( ilo.readQ() ); // reference price / 2
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24
|
||||
// write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_SellList: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertRelationChanged( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType();
|
||||
iln.setPacketType( ptype ); // ptype must be == PCODE_RELATIONCHANGED
|
||||
iln.writeD( 0x01 ); // T24 unknown - write to new, but dont read from old
|
||||
iln.writeD( ilo.readD() ); // objectID
|
||||
iln.writeD( ilo.readD() ); // relation
|
||||
iln.writeD( ilo.readD() ); // auto attackable
|
||||
iln.writeD( ilo.readD() ); // karma
|
||||
iln.writeD( ilo.readD() ); // pvpFlag
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_RelationChanged: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertExBuySellList( unsigned char *bytes, unsigned int len, unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
int count, i, ia;
|
||||
ilo.setBytes( bytes, len );
|
||||
//
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode FE
|
||||
iln.writeH( ilo.readH() ); // ext.opcode 00B7
|
||||
iln.writeQ( ilo.readQ() ); // money
|
||||
// first comes BuyList
|
||||
iln.writeD( ilo.readD() ); // buylist ID
|
||||
count = ilo.readH(); iln.writeH( (short)count );
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // type1
|
||||
iln.writeD( ilo.readD() ); // oid
|
||||
iln.writeD( ilo.readD() ); // iid
|
||||
iln.writeQ( ilo.readQ() ); // count
|
||||
iln.writeH( ilo.readH() ); // type2
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeD( ilo.readD() ); // bodypart
|
||||
iln.writeH( ilo.readH() ); // enchant level
|
||||
iln.writeH( ilo.readH() ); // 0x00
|
||||
iln.writeH( ilo.readH() ); // 0x00 // cust.type3?
|
||||
iln.writeQ( ilo.readQ() ); // price
|
||||
// elementals
|
||||
for( ia=0; ia<8; ia++ ) iln.writeH( ilo.readH() ); // elements
|
||||
// T24 enchant effects (dont read from old)
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
// next comes SellList
|
||||
count = ilo.readH(); iln.writeH( (short)count );
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // type1
|
||||
iln.writeD( ilo.readD() ); // oid
|
||||
iln.writeD( ilo.readD() ); // iid
|
||||
iln.writeQ( ilo.readQ() ); // count
|
||||
iln.writeH( ilo.readH() ); // type2
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeD( ilo.readD() ); // bodypart
|
||||
iln.writeH( ilo.readH() ); // enchant level
|
||||
iln.writeH( ilo.readH() ); // 0x00
|
||||
iln.writeH( ilo.readH() ); // 0x00 // cust.type3?
|
||||
iln.writeQ( ilo.readQ() ); // price
|
||||
// elementals
|
||||
for( ia=0; ia<8; ia++ ) iln.writeH( ilo.readH() ); // elements
|
||||
// T24 enchant effects (dont read from old)
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
// next comes refund list
|
||||
count = ilo.readH(); iln.writeH( (short)count );
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeD( ilo.readD() ); // refund list item idx
|
||||
iln.writeD( ilo.readD() ); // iid
|
||||
iln.writeQ( ilo.readQ() ); // count
|
||||
iln.writeH( ilo.readH() ); // type2
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // enchant level
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeQ( ilo.readQ() ); // price
|
||||
// elementals
|
||||
for( ia=0; ia<8; ia++ ) iln.writeH( ilo.readH() ); // elements
|
||||
// T24 enchant effects (dont read from old)
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
try
|
||||
{
|
||||
iln.writeC( ilo.readC() ); // _done
|
||||
}
|
||||
catch( L2P_ReadException& e )
|
||||
{
|
||||
UNREFERENCED_PARAMETER( e );
|
||||
iln.writeC( 0x00 ); // :(
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_ExBuySellList: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertWarehouseDepositList( unsigned char *bytes, unsigned int len, unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
int count, i, ia;
|
||||
ilo.setBytes( bytes, len );
|
||||
//
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode FE
|
||||
iln.writeH( ilo.readH() ); // WH type
|
||||
iln.writeQ( ilo.readQ() ); // adena
|
||||
count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // type1
|
||||
iln.writeD( ilo.readD() ); // oid
|
||||
iln.writeD( ilo.readD() ); // iid
|
||||
iln.writeQ( ilo.readQ() ); // cnt
|
||||
iln.writeH( ilo.readH() ); // type2
|
||||
iln.writeH( ilo.readH() ); // cust type1
|
||||
iln.writeD( ilo.readD() ); // b.part
|
||||
iln.writeH( ilo.readH() ); // ench
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // cust type2
|
||||
iln.writeD( ilo.readD() ); // oid
|
||||
iln.writeQ( ilo.readQ() ); // aug.related
|
||||
for( ia=0; ia<8; ia++ ) iln.writeH( ilo.readH() ); // elementals
|
||||
iln.writeD( ilo.readD() ); // mana
|
||||
iln.writeD( ilo.readD() ); // time
|
||||
// T24 enchant effects
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
log_error( LOG_ERROR, "ProtoConv_WarehouseDepositList: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertWarehouseWithdrawList( unsigned char *bytes, unsigned int len, unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
int count, i, ia;
|
||||
ilo.setBytes( bytes, len );
|
||||
//
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode FE
|
||||
iln.writeH( ilo.readH() ); // WH type
|
||||
iln.writeQ( ilo.readQ() ); // adena
|
||||
count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // type1
|
||||
iln.writeD( ilo.readD() ); // oid
|
||||
iln.writeD( ilo.readD() ); // iid
|
||||
iln.writeQ( ilo.readQ() ); // cnt
|
||||
iln.writeH( ilo.readH() ); // type2
|
||||
iln.writeH( ilo.readH() ); // cust type1
|
||||
iln.writeD( ilo.readD() ); // b.part
|
||||
iln.writeH( ilo.readH() ); // ench
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // cust type2
|
||||
iln.writeD( ilo.readD() ); // oid
|
||||
iln.writeQ( ilo.readQ() ); // aug.related
|
||||
for( ia=0; ia<8; ia++ ) iln.writeH( ilo.readH() ); // elementals
|
||||
iln.writeD( ilo.readD() ); // mana
|
||||
iln.writeD( ilo.readD() ); // time
|
||||
// T24 enchant effects
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
log_error( LOG_ERROR, "ProtoConv_WarehouseWithdrawalList: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertTradeStart( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode
|
||||
iln.writeD( ilo.readD() ); // partner objectId
|
||||
int count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // item type 1
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // item type 2
|
||||
iln.writeH( ilo.readH() ); // item custom type 1 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeH( ilo.readH() ); // item enchant level
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // item custom type 2 (pet name related..?)
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24 // write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_TradeStart: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertTradeOwnAdd( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode
|
||||
int count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // item type 1
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // item type 2
|
||||
iln.writeH( ilo.readH() ); // item custom type 1 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeH( ilo.readH() ); // item enchant level
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // item custom type 2 (pet name related..?)
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24 // write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_TradeOwnAdd: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertTradeOtherAdd( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode
|
||||
int count = ilo.readH(); iln.writeH( (short)count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeH( ilo.readH() ); // item type 1
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // item type 2
|
||||
iln.writeH( ilo.readH() ); // item custom type 1 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeH( ilo.readH() ); // item enchant level
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // item custom type 2 (pet name related..?)
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24 // write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_TradeOtherAdd: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertPrivateStoreListSell( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode
|
||||
iln.writeD( ilo.readD() ); // seller obejct ID
|
||||
iln.writeD( ilo.readD() ); // isPackageSale
|
||||
iln.writeQ( ilo.readQ() ); // player adena
|
||||
int count = ilo.readD(); iln.writeD( count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeD( ilo.readD() ); // item type 2
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // ench
|
||||
iln.writeH( ilo.readH() ); // item custom type 2 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeQ( ilo.readQ() ); // price
|
||||
iln.writeQ( ilo.readQ() ); // ref.price
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24 // write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_PrivateStoreListSell: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtoConv_ConvertPrivateStoreListBuy( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
L2GamePacket ilo; // old
|
||||
L2GamePacket iln; // new
|
||||
ilo.setBytes( bytes, len );
|
||||
unsigned char ptype = ilo.getPacketType(); iln.setPacketType( ptype ); // opcode
|
||||
iln.writeD( ilo.readD() ); // seller object ID
|
||||
iln.writeQ( ilo.readQ() ); // player adena
|
||||
int count = ilo.readD(); iln.writeD( count ); // items count
|
||||
int i, ie;
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
iln.writeD( ilo.readD() ); // item type 2
|
||||
iln.writeD( ilo.readD() ); // item object id
|
||||
iln.writeD( ilo.readD() ); // item item id
|
||||
iln.writeQ( ilo.readQ() ); // item count
|
||||
iln.writeH( ilo.readH() ); // 00
|
||||
iln.writeH( ilo.readH() ); // ench
|
||||
iln.writeH( ilo.readH() ); // item custom type 2 (always 0x00)
|
||||
iln.writeD( ilo.readD() ); // item bodypart
|
||||
iln.writeQ( ilo.readQ() ); // price
|
||||
iln.writeQ( ilo.readQ() ); // ref.price
|
||||
// T1 elementals
|
||||
for( ie=0; ie<8; ie++ ) iln.writeH( ilo.readH() ); // element. attrs
|
||||
// T24 // write enchant effects to new packet, but don't read them from source
|
||||
iln.writeH(0x00); iln.writeH(0x00); iln.writeH(0x00);
|
||||
}
|
||||
//
|
||||
(*newLen) = iln.getPacketSize();
|
||||
(*newBytes) = (unsigned char *)malloc( (*newLen) );
|
||||
if( (*newBytes) )
|
||||
{
|
||||
memcpy( (*newBytes), iln.getBytesPtr(), (*newLen) );
|
||||
return true;
|
||||
}
|
||||
|
||||
log_error( LOG_ERROR, "ProtoConv_PrivateStoreListBuy: some error after processing, "
|
||||
"len = %u, newLen = 0x%p, (*newLen) = %u, (*newBytes) = 0x%p\n",
|
||||
len, newLen, (*newLen), (*newBytes) );
|
||||
(*newLen) = len;
|
||||
(*newBytes) = bytes;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ProtoConv_ConvertPacket( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen )
|
||||
{
|
||||
if( !pconv_enabled ) return false;
|
||||
if( !pconv_was_Init ) ProtoConv_Init();
|
||||
if( !bytes || (len<3) || !newBytes || !newLen ) return false; // assert
|
||||
bool bRet = false;
|
||||
unsigned char pcode = bytes[2];
|
||||
unsigned short pcode2 = 0;
|
||||
if( len >= 5 ) pcode2 = bytes[3] | (((unsigned short)bytes[4]) << 8);
|
||||
|
||||
try { // C++ exception handler
|
||||
|
||||
if( pcode == 0xFE ) // extended server packet
|
||||
{
|
||||
switch( pcode2 )
|
||||
{
|
||||
case PCODE2_EXBUYSELLLITSTPACKET: bRet = ProtoConv_ConvertExBuySellList( bytes, len, newBytes, newLen ); break;
|
||||
default: log_error( LOG_ERROR, "ProtoConvert: convert not found for packet FE:%02X\n", (unsigned int)pcode ); break;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
if( pconv_table[ pcode ] == 0 )
|
||||
{
|
||||
log_error( LOG_ERROR, "ProtoConvert: convert not found for packet 0x%02X\n", (unsigned int)pcode );
|
||||
return false;
|
||||
}
|
||||
switch( pcode )
|
||||
{
|
||||
case PCODE_SELLLIST: bRet = ProtoConv_ConvertSellList( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_BUYLIST: bRet = ProtoConv_ConvertBuyList( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_ITEMLIST: bRet = ProtoConv_ConvertItemList( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_TRADESTART: bRet = ProtoConv_ConvertTradeStart( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_TRADEOWNADD: bRet = ProtoConv_ConvertTradeOwnAdd( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_TRADEOTHERADD: bRet = ProtoConv_ConvertTradeOtherAdd( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_INVENTORYUPDATE: bRet = ProtoConv_ConvertInventoryUpdate( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_WAREHOUSEDEPOSITLIST: bRet = ProtoConv_ConvertWarehouseDepositList( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_WAREHOUSEWITHDRAWLIST: bRet = ProtoConv_ConvertWarehouseWithdrawList( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_PRIVATESTORELISTSELL: bRet = ProtoConv_ConvertPrivateStoreListSell( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_PRIVATESTORELISTBUY: bRet = ProtoConv_ConvertPrivateStoreListBuy( bytes, len, newBytes, newLen ); break;
|
||||
case PCODE_RELATIONCHANGED: bRet = ProtoConv_ConvertRelationChanged( bytes, len, newBytes, newLen ); break;
|
||||
}
|
||||
|
||||
} // try
|
||||
catch( L2P_Exception& e )
|
||||
{
|
||||
log_error( LOG_ERROR, "ProtoConv_ConvertPacket: pcode = 0x%02X, pcode2 = 0x%02X\n"
|
||||
"L2P_Exception: %s\n", (unsigned int)pcode, (unsigned int)pcode2, e.what() );
|
||||
// cleanup (<28><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!)
|
||||
if( (*newBytes) != bytes ) free( (*newBytes) );
|
||||
(*newBytes) = bytes;
|
||||
(*newLen) = len;
|
||||
bRet = false;
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
11
l2detect/ProtocolConverter.h
Normal file
11
l2detect/ProtocolConverter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef H_PROTOCONV
|
||||
#define H_PROTOCONV
|
||||
|
||||
void ProtoConv_Init();
|
||||
int ProtoConv_IsEnabled();
|
||||
int ProtoConv_ConvExistsForPacket( unsigned char pcode );
|
||||
|
||||
bool ProtoConv_ConvertPacket( unsigned char *bytes, unsigned int len,
|
||||
unsigned char **newBytes, unsigned int *newLen );
|
||||
|
||||
#endif
|
||||
448
l2detect/RadarDllWnd.cpp
Normal file
448
l2detect/RadarDllWnd.cpp
Normal file
@@ -0,0 +1,448 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "RadarDllWnd.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
extern class GameClient *g_game_client;
|
||||
|
||||
#define RADARDLLWND_CLASS TEXT("RadarDllWindow_2.0")
|
||||
|
||||
// globals
|
||||
HINSTANCE g_radardll_hinst = NULL;
|
||||
DWORD g_radardll_thread_id = 0;
|
||||
HWND g_hWndL2 = NULL;
|
||||
DWORD g_l2_thread_id = 0;
|
||||
HWND g_radardll_hwnd = NULL;
|
||||
|
||||
// display globals
|
||||
int g_radarWnd_drawOnClient = 0;
|
||||
|
||||
LPDIRECTDRAW lpdd = NULL;
|
||||
LPDIRECTDRAW7 lpdd7 = NULL;
|
||||
LPDIRECTDRAWSURFACE7 lpdds7 = NULL;
|
||||
|
||||
// hook procs defs
|
||||
LRESULT CALLBACK KeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
|
||||
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
void InitDirectDraw( HWND hWnd );
|
||||
void CleanupDirectDraw();
|
||||
|
||||
BOOL RadarDllWindowRegClass( HINSTANCE hInst )
|
||||
{
|
||||
g_radardll_hinst = hInst;
|
||||
WNDCLASSEX wc;
|
||||
memset( &wc, 0, sizeof(WNDCLASSEX) );
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wc.hInstance = hInst;
|
||||
wc.hIcon = wc.hIconSm = LoadIcon( g_radardll_hinst, MAKEINTRESOURCE(IDI_MFC) );
|
||||
wc.lpszClassName = RADARDLLWND_CLASS;
|
||||
wc.style = CS_OWNDC | /*CS_VREDRAW | CS_HREDRAW |*/ CS_DBLCLKS;
|
||||
wc.lpfnWndProc = RadarDllWindowProc;
|
||||
if( !RegisterClassEx( &wc ) )
|
||||
{
|
||||
MessageBox( 0, TEXT("RegisterClassEx() failed!"), TEXT("Error!"), MB_ICONSTOP );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HWND RadarDllWindowCreate()
|
||||
{
|
||||
if( g_radardll_hinst == NULL ) return NULL;
|
||||
DWORD windowExStyle = WS_EX_LAYERED | WS_EX_TOPMOST; // | WS_EX_TOOLWINDOW /*| WS_EX_NOACTIVATE*/;
|
||||
DWORD windowStyle = WS_OVERLAPPEDWINDOW;
|
||||
if( g_cfg.isInGameMode == false )
|
||||
{
|
||||
windowExStyle = WS_EX_LAYERED; // NO WS_EX_TOPMOST; // :)
|
||||
windowStyle |= ( WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX );
|
||||
}
|
||||
HWND hWndRadar = NULL;
|
||||
hWndRadar = CreateWindowEx( windowExStyle, RADARDLLWND_CLASS, TEXT("L2Detect"), windowStyle,
|
||||
0, 0, 300, 800, NULL, NULL, g_radardll_hinst, NULL );
|
||||
if( !hWndRadar )
|
||||
{
|
||||
log_error( LOG_ERROR, "Radar window creation failed, trying to init common controls...\n" );
|
||||
MyInitCommonControlsEx();
|
||||
hWndRadar = CreateWindowEx( windowExStyle, RADARDLLWND_CLASS, TEXT("L2Detect"), windowStyle,
|
||||
0, 0, 300, 800, NULL, NULL, g_radardll_hinst, NULL );
|
||||
if( !hWndRadar )
|
||||
{
|
||||
log_error( LOG_ERROR, "Radar window creation failed again. Radar will not function!\n" );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
SetLayeredWindowAttributes( hWndRadar, RGB(0,0,0), 255, /*LWA_COLORKEY |*/ LWA_ALPHA );
|
||||
return hWndRadar;
|
||||
}
|
||||
|
||||
void RadarDllWindowStart( HINSTANCE hInst )
|
||||
{
|
||||
RadarDllWindowRegClass( hInst );
|
||||
HANDLE hThread = NULL;
|
||||
DWORD dwTID = 0;
|
||||
hThread = (HANDLE)_beginthreadex( NULL, 0,
|
||||
(unsigned int (__stdcall *)(void *))RadarDllWindowThread, NULL, 0,
|
||||
(unsigned int *)&dwTID );
|
||||
if( hThread == NULL )
|
||||
{
|
||||
MessageBox( 0, TEXT("RadarDllWindowThread create error!"), TEXT("Error!"), MB_ICONSTOP );
|
||||
return;
|
||||
}
|
||||
CloseHandle( hThread );
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>-<2D><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EnumWindows
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> hWnd
|
||||
BOOL CALLBACK RadarDllWindowThread_EnumWindowsProc( HWND hWnd, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
DWORD myPid = GetCurrentProcessId(); // pID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
DWORD dwPid = 0;
|
||||
DWORD dwTid = GetWindowThreadProcessId( hWnd, &dwPid ); // pID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2<> <20><><EFBFBD><EFBFBD> <20>2
|
||||
if( dwPid == myPid ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>2
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "RadarDllWindowThread_EnumWindowsProc(): got window pid,tid = (%u,%u)\n",
|
||||
(unsigned int)dwPid, (unsigned int)dwTid );
|
||||
// window is running in the same process as we are
|
||||
// check window class or name to check is it is main Lineage II window
|
||||
bool isL2Window = false;
|
||||
TCHAR wndTitle[256];
|
||||
memset( wndTitle, 0, sizeof(wndTitle) );
|
||||
GetWindowText( hWnd, wndTitle, 255 );
|
||||
log_error( LOG_DEBUGDUMP, ".. got window title [%S]\n", wndTitle );
|
||||
if( _tcsicmp( wndTitle, _T("Lineage II") ) == 0 )
|
||||
{
|
||||
isL2Window = true;
|
||||
log_error( LOG_DEBUG, "... found L2 window by title!\n" );
|
||||
}
|
||||
// title doesn't match? check window class name!
|
||||
if( !isL2Window )
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, "... window title doesn't match, trying by class name...\n" );
|
||||
TCHAR buffer_for_class_name[256] = {0};
|
||||
if( GetClassName( hWnd, buffer_for_class_name, 255 ) )
|
||||
{
|
||||
log_error( LOG_DEBUGDUMP, ".... got window class name = [%S]\n", buffer_for_class_name );
|
||||
if( _tcsicmp( buffer_for_class_name, _T("l2UnrealWWindowsViewportWindow") ) == 0 )
|
||||
{
|
||||
isL2Window = true;
|
||||
log_error( LOG_DEBUG, ".... found L2 window by class name!\n" );
|
||||
}
|
||||
}
|
||||
else
|
||||
ErrorLogger_LogLastError( "GetClassName()", GetLastError() );
|
||||
}
|
||||
// checks...
|
||||
if( isL2Window ) // found
|
||||
{
|
||||
g_hWndL2 = hWnd; // save in global var
|
||||
g_l2_thread_id = dwTid;
|
||||
return FALSE; // stop EnumWindows
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HHOOK WINAPI RadarDllWindowThread_installKeyboardHook()
|
||||
{
|
||||
HHOOK hook = NULL;
|
||||
unsigned int my_process_id = (unsigned int)GetCurrentProcessId();
|
||||
log_error( LOG_DEBUG, "We're running in process id #%u\n", my_process_id );
|
||||
g_hWndL2 = NULL; // global handle to L2 Window
|
||||
g_l2_thread_id = 0;
|
||||
int tries = 80; // wait 20 seconds for L2 widnow
|
||||
log_error( LOG_OK, "RadarDllWindowThread_installKeyboardHook(): looking for L2 window ... " );
|
||||
while( g_hWndL2 == NULL )
|
||||
{
|
||||
EnumWindows( RadarDllWindowThread_EnumWindowsProc, 0 );
|
||||
tries--;
|
||||
if( g_hWndL2 == NULL )
|
||||
log_error_np( LOG_OK, "%d, ", tries );
|
||||
if( tries <= 0 ) break;
|
||||
Sleep( 250 ); // wait 0.25 seconds, maybe L2 window will appear
|
||||
}
|
||||
log_error_np( LOG_OK, "\n" );
|
||||
// check if window is found
|
||||
if( g_hWndL2 )
|
||||
{
|
||||
hook = SetWindowsHookEx( WH_KEYBOARD, KeyboardProc, g_radardll_hinst, g_l2_thread_id );
|
||||
if( hook == NULL )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
ErrorLogger_LogLastError( "SetWindowsHookEx() failed", le );
|
||||
}
|
||||
else
|
||||
log_error( LOG_OK, "Window keyboard hook installed.\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "RadarDllWindowThread_installKeyboardHook(): cannot find Lineage II window!!!\n" );
|
||||
g_hWndL2 = NULL;
|
||||
}
|
||||
return hook;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI RadarDllWindowThread( LPVOID lpParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lpParam);
|
||||
g_radardll_thread_id = GetCurrentThreadId();
|
||||
|
||||
// are we in ingame or outgame?
|
||||
TCHAR tszEvtName[256];
|
||||
wsprintf( tszEvtName, TEXT("L2Detect Outgame Event_%d"), (unsigned)GetCurrentProcessId() );
|
||||
HANDLE hEvtDbg = OpenEvent( EVENT_MODIFY_STATE, FALSE, tszEvtName );
|
||||
|
||||
HHOOK hook = NULL;
|
||||
|
||||
if( hEvtDbg == NULL ) // ingame, wait for L2 Window
|
||||
{
|
||||
g_cfg.isInGameMode = true;
|
||||
Sleep( 5000 );
|
||||
// install keyboard hook
|
||||
hook = RadarDllWindowThread_installKeyboardHook();
|
||||
// wait more till L2 window initialises
|
||||
Sleep( 4000 );
|
||||
//MyInitCommonControlsEx();
|
||||
//InitDirectDraw( hWndL2 );
|
||||
}
|
||||
else // outgame. do not wait for anything
|
||||
{
|
||||
g_cfg.isInGameMode = false;
|
||||
}
|
||||
//
|
||||
|
||||
ErrorLogger_FlushLogFile();
|
||||
//
|
||||
HWND hWnd = RadarDllWindowCreate();
|
||||
if( hWnd == NULL )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
log_error( LOG_ERROR, "RadarDllWindowCreate() failed! last error %u\n", (unsigned int)le );
|
||||
ErrorLogger_LogLastError( "RadarDllWindowCreate()", le );
|
||||
return le;
|
||||
}
|
||||
g_radardll_hwnd = hWnd; // save radar window handle in global var
|
||||
// hide radar window ONLY if is INGAME mode AND Lineage II window is found!
|
||||
if( (g_cfg.isInGameMode == true) && (g_hWndL2 != NULL) )
|
||||
ShowWindow( hWnd, SW_HIDE );
|
||||
// fix: show radar window again in INGAME mode and if Lineage II window was not found
|
||||
if( (g_cfg.isInGameMode == true) && (g_hWndL2 == NULL) )
|
||||
ShowWindow( hWnd, SW_SHOWNORMAL );
|
||||
|
||||
// radar wnd message loop
|
||||
MSG msg;
|
||||
while( GetMessage( &msg, NULL, 0, 0 ) )
|
||||
{
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
//
|
||||
log_error( LOG_DEBUG, "Window is closed. Cleanup...\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
|
||||
// Cleanup
|
||||
if( g_cfg.isInGameMode )
|
||||
{
|
||||
// unhook hook installed in ingame mode
|
||||
UnhookWindowsHookEx( hook );
|
||||
CleanupDirectDraw();
|
||||
}
|
||||
else
|
||||
{
|
||||
// signal EXE in outgame mode to stop
|
||||
SetEvent( hEvtDbg );
|
||||
CloseHandle( hEvtDbg );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// local thread's keyboard hook
|
||||
LRESULT CALLBACK KeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if( nCode < 0 ) return CallNextHookEx( NULL, nCode, wParam, lParam );
|
||||
if( nCode == HC_ACTION || nCode == HC_NOREMOVE )
|
||||
{
|
||||
//wParam [in] Specifies the virtual-key code of the key that generated the keystroke message.
|
||||
//lParam [in] Specifies the repeat count, scan code, extended-key flag, context code,
|
||||
// previous key-state flag, and transition-state flag
|
||||
//lParam bit 31 is set if key is pressed, and not set if released
|
||||
bool keyIsPushed = ((lParam & 0x80000000) != 0);
|
||||
if( keyIsPushed ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
switch( wParam ) // wParam - <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
{
|
||||
case VK_PAUSE: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pause/Break?
|
||||
PostMessage( g_radardll_hwnd, WMMY_WNDSHOWTOGGLE, 0, 0 );
|
||||
break;
|
||||
default: // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if( g_game_client )
|
||||
g_game_client->ai.notifyUIKeyUp( (int)wParam );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// [DBG] KeyboardProc( 0, '' 19, 0xC0450001 ) cur thread: 5088 5088: l2 thread
|
||||
//log_error( LOG_DEBUG, "KeyboardProc( %d, '%c' %d, 0x%08X ) cur thread: %u %u: l2 thread\n",
|
||||
// nCode, (char)wParam, (int)wParam, (unsigned int)lParam,
|
||||
// (unsigned int)GetCurrentThreadId(), (unsigned int)g_l2_thread_id );
|
||||
return CallNextHookEx( NULL, nCode, wParam, lParam );
|
||||
}
|
||||
|
||||
// global keyboard hook
|
||||
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if( nCode < 0 ) return CallNextHookEx( NULL, nCode, wParam, lParam );
|
||||
//
|
||||
//char szMes[32] = {0};
|
||||
//switch( wParam )
|
||||
//{
|
||||
//case WM_KEYDOWN: strcpy( szMes, "WM_KEYDOWN " ); break;
|
||||
//case WM_KEYUP: strcpy( szMes, "WM_KEYUP " ); break;
|
||||
//case WM_SYSKEYDOWN: strcpy( szMes, "WM_SYSKEYDOWN" ); break;
|
||||
//case WM_SYSKEYUP: strcpy( szMes, "WM_SYSKEYUP " ); break;
|
||||
//default: sprintf( szMes, "mes_%u", (unsigned int)wParam ); break;
|
||||
//}
|
||||
//
|
||||
KBDLLHOOKSTRUCT *phs = (KBDLLHOOKSTRUCT *)lParam;
|
||||
if( !phs ) return CallNextHookEx( NULL, nCode, wParam, lParam );
|
||||
//
|
||||
//log_error( LOG_DEBUG, "LowLevelKeyboardProc( %d, '%s', '%3c' %4u, %u ) threads (cur/radar/l2): %u/%u/%u\n",
|
||||
// nCode, szMes, (char)(phs->vkCode), (unsigned int)(phs->vkCode), (unsigned int)phs->scanCode,
|
||||
// (unsigned int)GetCurrentThreadId(), (unsigned int)g_radardll_thread_id, (unsigned int)g_l2_thread_id );
|
||||
//
|
||||
if( wParam == WM_KEYUP )
|
||||
{
|
||||
if( phs->vkCode == VK_PAUSE )
|
||||
PostMessage( g_radardll_hwnd, WMMY_WNDSHOWTOGGLE, 0, 0 );
|
||||
if( phs->vkCode == VK_NUMLOCK )
|
||||
{
|
||||
int new_val = 0;
|
||||
if( g_radarWnd_drawOnClient == 0 ) new_val = 1;
|
||||
g_radarWnd_drawOnClient = new_val;
|
||||
}
|
||||
}
|
||||
return CallNextHookEx( NULL, nCode, wParam, lParam );
|
||||
}
|
||||
|
||||
void InitDirectDraw( HWND hWnd )
|
||||
{
|
||||
// Window info
|
||||
if( hWnd != NULL )
|
||||
{
|
||||
TCHAR cn[256] = {0};
|
||||
GetClassName( hWnd, cn, 255 );
|
||||
log_error( LOG_DEBUG, "Got class name: [%S]\n", cn );
|
||||
}
|
||||
// Create DirectDraw object
|
||||
HRESULT hRes = DirectDrawCreate( NULL, &lpdd, NULL );
|
||||
if( hRes != S_OK )
|
||||
{
|
||||
log_error( LOG_ERROR, "DirectDraw creating failed! HRESULT = %d (%08X), last error %u\n",
|
||||
hRes, hRes, (unsigned int)GetLastError() );
|
||||
return;
|
||||
}
|
||||
log_error( LOG_DEBUG, "DirectDraw create OK\n" );
|
||||
// get directdraw7
|
||||
hRes = lpdd->QueryInterface( IID_IDirectDraw7, (void **)&lpdd7 );
|
||||
lpdd->Release();
|
||||
lpdd = NULL;
|
||||
if( hRes != S_OK )
|
||||
{
|
||||
log_error( LOG_ERROR, "IDirectDraw::QueryInterface() failed! err 0x%08x\n", hRes );
|
||||
return;
|
||||
}
|
||||
log_error( LOG_DEBUG, "DirectDraw7 create OK\n" );
|
||||
// try to set cooperative level (dest HWND)
|
||||
hRes = lpdd7->SetCooperativeLevel( hWnd, DDSCL_NORMAL /* | DDSCL_MULTITHREADED */ );
|
||||
if( hRes != S_OK ) log_error( LOG_ERROR, "IDirectDraw7::SetCooperativeLevel() failed! 0x%08X\n", hRes );
|
||||
else log_error( LOG_DEBUG, "IDirectDraw7::SetCooperativeLevel() OK\n" );
|
||||
//
|
||||
/*HDC hdcL2 = GetDC( hWnd );
|
||||
hRes = lpdd7->GetSurfaceFromDC( hdcL2, &lpdds );
|
||||
if( hRes != S_OK )
|
||||
{
|
||||
log_error( LOG_ERROR, "IDirectDraw7::GetSurfaceFromDC() failed! 0x%08x\n", hRes );
|
||||
switch( hRes )
|
||||
{
|
||||
case DDERR_GENERIC: log_error( LOG_ERROR, "DDERR_GENERIC\n" ); break;
|
||||
case DDERR_INVALIDPARAMS: log_error( LOG_ERROR, "DDERR_INVALIDPARAMS\n" ); break;
|
||||
case DDERR_OUTOFMEMORY: log_error( LOG_ERROR, "DDERR_OUTOFMEMORY\n" ); break;
|
||||
case DDERR_NOTFOUND: log_error( LOG_ERROR, "DDERR_NOTFOUND\n" ); break;
|
||||
default: log_error( LOG_ERROR, "xz\n" ); break;
|
||||
}
|
||||
}
|
||||
else log_error( LOG_DEBUG, "IDirectDraw7::GetSurfaceFromDC() OK! 0x%08x\n", lpdds );
|
||||
ReleaseDC( hWnd, hdcL2 );*/
|
||||
//
|
||||
/*DDSURFACEDESC2 sd2;
|
||||
sd2.dwSize = sizeof(sd2);
|
||||
sd2.ddsCaps.dwCaps;
|
||||
lpdd7->CreateSurface( &sd2, &lpdds7, NULL );*/
|
||||
}
|
||||
|
||||
void CleanupDirectDraw()
|
||||
{
|
||||
if( lpdds7 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Releasing Surface...\n" );
|
||||
lpdds7->Release();
|
||||
lpdds7 = NULL;
|
||||
}
|
||||
if( lpdd7 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Releasing IDirectDraw7...\n" );
|
||||
lpdd7->Release();
|
||||
lpdd7 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// old hook installer code
|
||||
/*
|
||||
// find Lineage II Window
|
||||
HWND hWndL2;
|
||||
int maxTries = 50;
|
||||
DWORD l2_pid = 0, l2_tid = 0;
|
||||
while( maxTries > 0 )
|
||||
{
|
||||
maxTries--;
|
||||
// try to find by name
|
||||
hWndL2 = FindWindow( NULL, TEXT("Lineage II") );
|
||||
if( hWndL2 ) log_error( LOG_DEBUG, "Found L2 Window by name 0x%p\n", hWndL2 );
|
||||
else
|
||||
{
|
||||
// or else try to find by class
|
||||
hWndL2 = FindWindow( TEXT("l2UnrealWWindowsViewportWindow"), NULL );
|
||||
if( hWndL2 ) log_error( LOG_DEBUG, "Found L2 Window by class 0x%p\n", hWndL2 );
|
||||
else log_error( LOG_WARNING, "FindWindow() cannot find L2 Window! (triesLeft: %d)\n", maxTries );
|
||||
}
|
||||
Sleep( 1000 );
|
||||
if( hWndL2 != NULL )
|
||||
{
|
||||
g_hWndL2 = hWndL2;
|
||||
l2_tid = GetWindowThreadProcessId( hWndL2, &l2_pid );
|
||||
g_l2_thread_id = l2_tid;
|
||||
log_error( LOG_DEBUG, "L2 Window Thread: %d, process ID: %d\n", l2_tid, l2_pid );
|
||||
break;
|
||||
}
|
||||
}
|
||||
// install keyboard hook only in ingame mode
|
||||
//hook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, g_radardll_hinst, 0 );
|
||||
hook = SetWindowsHookEx( WH_KEYBOARD, KeyboardProc, g_radardll_hinst, g_l2_thread_id );
|
||||
if( hook == NULL )
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
ErrorLogger_LogLastError( "SetWindowsHookEx() failed", le );
|
||||
}
|
||||
else
|
||||
log_error( LOG_DEBUG, "SetWindowsHookEx() OK\n" );
|
||||
*/
|
||||
56
l2detect/RadarDllWnd.h
Normal file
56
l2detect/RadarDllWnd.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef H_RADAR_WND
|
||||
#define H_RADAR_WND
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern HWND g_radardll_hwnd;
|
||||
extern DWORD g_radardll_thread_id;
|
||||
extern DWORD g_l2_thread_id;
|
||||
|
||||
LRESULT CALLBACK RadarDllWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
BOOL RadarDllWindowRegClass( HINSTANCE hInst );
|
||||
HWND RadarDllWindowCreate();
|
||||
|
||||
DWORD WINAPI RadarDllWindowThread( LPVOID lpParam );
|
||||
void RadarDllWindowStart( HINSTANCE hInst );
|
||||
|
||||
#define WMMY_WNDSHOWTOGGLE (WM_USER+100)
|
||||
#define WMMY_UPDATE_CHARS_LIST (WM_USER+101)
|
||||
#define WMMY_SET_USER_COORDS (WM_USER+102) // unused
|
||||
#define WMMY_UPDATE_NPCS_LIST (WM_USER+103)
|
||||
#define WMMY_TRAYMESSAGE (WM_USER+104)
|
||||
#define WMMY_GAMECLIENT_NOTIFY (WM_USER+105)
|
||||
#define WMMY_LOGINCLIENT_NOTIFY (WM_USER+106)
|
||||
#define WMMY_NOTIFY_TARGET (WM_USER+107)
|
||||
#define WMMY_UPDATE_CHECKS (WM_USER+108)
|
||||
#define WMMY_SAVE_WINDOW_SIZE (WM_USER+109)
|
||||
|
||||
// new way of lists updating
|
||||
#define WMMY_ADD_OBJECT (WM_USER+110) // msg
|
||||
#define WMMY_DEL_OBJECT (WM_USER+111) // msg
|
||||
#define WMMY_UPDATE_OBJECT (WM_USER+112) // msg
|
||||
// wParams for these messages
|
||||
#define MSG_PC 1
|
||||
#define MSG_NPC 2
|
||||
// lParams will represent objectId
|
||||
|
||||
#define WMMY_FORCE_UPDATE_LIST (WM_USER+113) // msg
|
||||
#define FORCE_UPDATE_CHARS_LIST 1 // wparam
|
||||
#define FORCE_UPDATE_NPCS_LIST 2 // wparam
|
||||
|
||||
void RadarWnd_NotifyTarget( unsigned int oid_from, unsigned int oid_to, bool selected = true );
|
||||
|
||||
// new lists update way
|
||||
void RadarWnd_AddChar( unsigned int objectId );
|
||||
void RadarWnd_UpdChar( unsigned int objectId );
|
||||
void RadarWnd_DelChar( unsigned int objectId );
|
||||
|
||||
void RadarWnd_AddNpc( unsigned int objectId );
|
||||
void RadarWnd_UpdNpc( unsigned int objectId );
|
||||
void RadarWnd_DelNpc( unsigned int objectId );
|
||||
|
||||
void RadarWnd_ForceUpdateCharsList();
|
||||
void RadarWnd_ForceUpdateNpcsList();
|
||||
|
||||
void RadarWnd_UpdateChecksState();
|
||||
|
||||
#endif /* H_RADAR_WND */
|
||||
42
l2detect/RadarDllWndCfg.cpp
Normal file
42
l2detect/RadarDllWndCfg.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "stdafx.h"
|
||||
#include "RadarDllWndCfg.h"
|
||||
|
||||
void RadarWndCfg_InitDefault( RADARWNDCFG *pCfg )
|
||||
{
|
||||
memset( pCfg, 0, sizeof(RADARWNDCFG) );
|
||||
pCfg->ui.colors.bgColor = RGB(0,0,0);
|
||||
pCfg->ui.colors.circleColor = RGB(128,128,128);
|
||||
pCfg->ui.colors.npcColor = RGB(200,200,0);
|
||||
pCfg->ui.colors.mobColor = RGB(128,0,0);
|
||||
pCfg->ui.colors.pcColor = RGB(75,75,255);
|
||||
pCfg->ui.colors.pcColorDead = RGB(75,75,75);
|
||||
pCfg->ui.colors.pcColorWar = RGB(255,85,85);
|
||||
pCfg->ui.colors.pcColorWarDead = RGB(155,65,65);
|
||||
pCfg->ui.colors.pcColorParty = RGB(60,255,60);
|
||||
pCfg->ui.colors.pcColorPartyDead = RGB(0,200,0);
|
||||
}
|
||||
|
||||
void RadarWndCfg_LoadConfigFromFile( RADARWNDCFG *pCfg, const char *fileName )
|
||||
{
|
||||
if( !pCfg ) return;
|
||||
char *useFN = (char *)fileName;
|
||||
if( !useFN ) useFN = "L2Detect_colors.ini";
|
||||
FILE *f = fopen( useFN, "rb" );
|
||||
if( !f ) return;
|
||||
fread( pCfg, 1, sizeof(RADARWNDCFG), f );
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
void RadarWndCfg_SaveConfigToFile( RADARWNDCFG *pCfg, const char *fileName )
|
||||
{
|
||||
if( !pCfg ) return;
|
||||
char *useFN = (char *)fileName;
|
||||
if( !useFN ) useFN = "L2Detect_colors.ini";
|
||||
FILE *f = fopen( useFN, "wb" );
|
||||
if( !f ) return;
|
||||
//
|
||||
fwrite( pCfg, 1, sizeof(RADARWNDCFG), f );
|
||||
//
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
29
l2detect/RadarDllWndCfg.h
Normal file
29
l2detect/RadarDllWndCfg.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef H_RADARDLLWND_CFG
|
||||
#define H_RADARDLLWND_CFG
|
||||
|
||||
struct RADARWNDCFG
|
||||
{
|
||||
struct st_ui
|
||||
{
|
||||
struct st_colors
|
||||
{
|
||||
COLORREF bgColor; // = RGB(0,0,0);
|
||||
COLORREF circleColor; // = RGB(127,128,128);
|
||||
COLORREF npcColor; // = RGB(200,200,0);
|
||||
COLORREF mobColor; // = RGB(128,0,0);
|
||||
COLORREF pcColor; // = RGB(75,75,255);
|
||||
COLORREF pcColorDead; // = RGB(75,75,75);
|
||||
COLORREF pcColorWar; // = RGB(255,85,85);
|
||||
COLORREF pcColorWarDead; // = RGB(155,65,65);
|
||||
COLORREF pcColorParty; // = RGB(60,255,60);
|
||||
COLORREF pcColorPartyDead; // = RGB(0,200,0);
|
||||
} colors;
|
||||
} ui;
|
||||
};
|
||||
|
||||
void RadarWndCfg_InitDefault( RADARWNDCFG *pCfg );
|
||||
|
||||
void RadarWndCfg_LoadConfigFromFile( RADARWNDCFG *pCfg, const char *fileName );
|
||||
void RadarWndCfg_SaveConfigToFile( RADARWNDCFG *pCfg, const char *fileName );
|
||||
|
||||
#endif
|
||||
27
l2detect/RadarDllWndHWID.cpp
Normal file
27
l2detect/RadarDllWndHWID.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "RadarDllWndHWID.h"
|
||||
#include "HWID.h"
|
||||
|
||||
DWORD WINAPI RadarDllWnd_HWID_Check_Thread( LPVOID lpParam )
|
||||
{
|
||||
HWND hWnd = (HWND)lpParam;
|
||||
//log_error( LOG_DEBUG, "RadarDllWnd_HWID_Check_Thread: started, sleeping...\n" );
|
||||
Sleep( 1000 );
|
||||
if( !VerifyHWID() )
|
||||
{
|
||||
log_error( LOG_ERROR, "RadarDllWnd_HWID_Check_Thread: HWID check failed!\n" );
|
||||
PostMessage( hWnd, WM_CLOSE, 0, 0 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RadarDllWnd_Start_HWID_Check( HWND hWnd )
|
||||
{
|
||||
HANDLE hThread = NULL;
|
||||
unsigned int tid = 0;
|
||||
hThread = (HANDLE)_beginthreadex( NULL, 0,
|
||||
(unsigned int (__stdcall *)(void *))RadarDllWnd_HWID_Check_Thread, (void *)hWnd,
|
||||
0, &tid );
|
||||
if( hThread ) CloseHandle( hThread );
|
||||
}
|
||||
6
l2detect/RadarDllWndHWID.h
Normal file
6
l2detect/RadarDllWndHWID.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RADARDLLWND_HWID
|
||||
#define H_RADARDLLWND_HWID
|
||||
|
||||
void RadarDllWnd_Start_HWID_Check( HWND hWnd );
|
||||
|
||||
#endif
|
||||
1623
l2detect/RadarDllWndProc.cpp
Normal file
1623
l2detect/RadarDllWndProc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
54
l2detect/RadarDllWndSize.cpp
Normal file
54
l2detect/RadarDllWndSize.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "RadarDllWndSize.h"
|
||||
|
||||
void RadarDllWnd_RestoreWindowSize( HWND hWnd )
|
||||
{
|
||||
HKEY hKey = NULL;
|
||||
if( RegOpenKeyEx( HKEY_CURRENT_USER, TEXT("Software\\L2Detect"), 0, KEY_READ, &hKey ) == NO_ERROR )
|
||||
{
|
||||
DWORD dwType = REG_DWORD, cb = 4;
|
||||
int x0 = 0, y0 = 0, w = 0, h = 0;
|
||||
cb = 4; RegQueryValueEx( hKey, TEXT("x0"), NULL, &dwType, (LPBYTE)&x0, &cb );
|
||||
cb = 4; RegQueryValueEx( hKey, TEXT("y0"), NULL, &dwType, (LPBYTE)&y0, &cb );
|
||||
cb = 4; RegQueryValueEx( hKey, TEXT("w"), NULL, &dwType, (LPBYTE)&w, &cb );
|
||||
cb = 4; RegQueryValueEx( hKey, TEXT("h"), NULL, &dwType, (LPBYTE)&h, &cb );
|
||||
if( x0 < 0 ) x0 = 1;
|
||||
if( y0 < 0 ) y0 = 1;
|
||||
if( x0 > 1200 ) x0 = 1200;
|
||||
if( y0 > 1000 ) y0 = 1000;
|
||||
if( w < 50 ) w = 50;
|
||||
if( h < 100 ) h = 100;
|
||||
if( x0>0 && y0>0 && w>0 && h>0 )
|
||||
MoveWindow( hWnd, x0, y0, w, h, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD le = GetLastError();
|
||||
ErrorLogger_LogLastError( "RadarDllWnd_RestoreWindowSize(): RegOpenKeyEx() failed", le );
|
||||
}
|
||||
}
|
||||
|
||||
void RadarDllWnd_SaveWidowSize( HWND hWnd )
|
||||
{
|
||||
RECT r;
|
||||
GetWindowRect( hWnd, &r );
|
||||
HKEY hKey = NULL;
|
||||
DWORD disp = 0;
|
||||
if( RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Software\\L2Detect"), 0, NULL,
|
||||
0, KEY_READ | KEY_WRITE, NULL, &hKey, &disp ) == NO_ERROR )
|
||||
{
|
||||
if( disp == REG_CREATED_NEW_KEY )
|
||||
log_error( LOG_DEBUG, "RadarDllWnd_SaveWidowSize(): created key\n" );
|
||||
if( disp == REG_OPENED_EXISTING_KEY )
|
||||
log_error( LOG_DEBUG, "RadarDllWnd_SaveWidowSize(): opened existing key\n" );
|
||||
RegSetValueEx( hKey, TEXT("x0"), 0, REG_DWORD, (LPCBYTE)&r.left, 4 );
|
||||
RegSetValueEx( hKey, TEXT("y0"), 0, REG_DWORD, (LPCBYTE)&r.top, 4 );
|
||||
DWORD dw = r.right - r.left;
|
||||
RegSetValueEx( hKey, TEXT("w"), 0, REG_DWORD, (LPCBYTE)&dw, 4 );
|
||||
dw = r.bottom - r.top;
|
||||
RegSetValueEx( hKey, TEXT("h"), 0, REG_DWORD, (LPCBYTE)&dw, 4 );
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
else ErrorLogger_LogLastError( "RadarDllWnd_SaveWidowSize(): RegCreateKeyEx() failed", GetLastError() );
|
||||
}
|
||||
4
l2detect/RadarDllWndSize.h
Normal file
4
l2detect/RadarDllWndSize.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void RadarDllWnd_RestoreWindowSize( HWND hWnd );
|
||||
void RadarDllWnd_SaveWidowSize( HWND hWnd );
|
||||
897
l2detect/RadarDllWnd_Lists.cpp
Normal file
897
l2detect/RadarDllWnd_Lists.cpp
Normal file
@@ -0,0 +1,897 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "RadarDllWnd.h"
|
||||
#include "WorldObjectTree.h"
|
||||
#include "CharArray.h"
|
||||
#include "NpcArray.h"
|
||||
#include "utils.h"
|
||||
#include "GameClient.h"
|
||||
extern GameClient *g_game_client;
|
||||
#include "ConfigIni.h"
|
||||
extern CConfig g_cfg;
|
||||
#include "windowUtils.h"
|
||||
|
||||
void RadarWnd_AddChar( unsigned int objectId ) { PostMessage( g_radardll_hwnd, WMMY_ADD_OBJECT, MSG_PC, (LPARAM)objectId ); }
|
||||
|
||||
void RadarWnd_UpdChar( unsigned int objectId ) { PostMessage( g_radardll_hwnd, WMMY_UPDATE_OBJECT, MSG_PC, (LPARAM)objectId ); }
|
||||
|
||||
void RadarWnd_DelChar( unsigned int objectId ) { PostMessage( g_radardll_hwnd, WMMY_DEL_OBJECT, MSG_PC, (LPARAM)objectId ); }
|
||||
|
||||
void RadarWnd_AddNpc( unsigned int objectId ) { PostMessage( g_radardll_hwnd, WMMY_ADD_OBJECT, MSG_NPC, (LPARAM)objectId ); }
|
||||
|
||||
void RadarWnd_UpdNpc( unsigned int objectId ) { PostMessage( g_radardll_hwnd, WMMY_UPDATE_OBJECT, MSG_NPC, (LPARAM)objectId ); }
|
||||
|
||||
void RadarWnd_DelNpc( unsigned int objectId ) { PostMessage( g_radardll_hwnd, WMMY_DEL_OBJECT, MSG_NPC, (LPARAM)objectId ); }
|
||||
|
||||
// forwards
|
||||
void RW_DeleteCharFromEnemiesList( unsigned int objectID );
|
||||
void RW_UpdateCharInEnemiesList( L2Player *cha );
|
||||
|
||||
extern HWND g_rw_hWndCL; // chars ListView window
|
||||
extern HWND g_rw_hWndNPC; // npcs ListView window
|
||||
extern HWND g_rw_hWndEnemies; // enemies ListView window
|
||||
extern bool g_radarwnd_npc_displayEnable;
|
||||
|
||||
LRESULT RW_OnAddObject( HWND hWnd, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hWnd);
|
||||
// do not add npc if not displaying
|
||||
if( wParam == MSG_NPC && !g_radarwnd_npc_displayEnable ) return 0;
|
||||
|
||||
unsigned int objectId = (unsigned int)lParam;
|
||||
L2OBJECT_TYPE objType = L2OT_NONE;
|
||||
int index = -1;
|
||||
if( !WorldObjectTree_GetInfoByObjectID( objectId, &objType, &index ) )
|
||||
{
|
||||
log_error( LOG_WARNING, "RW_OnAddObject(): cannot get info about object [%u] to add\n", objectId );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_z = g_game_client->ai.usr.z;
|
||||
|
||||
switch( wParam )
|
||||
{
|
||||
case MSG_PC:
|
||||
{
|
||||
if( objType != L2OT_PC )
|
||||
{
|
||||
log_error( LOG_WARNING, "RW_OnAddObject(): object [%u]: adding player, but in WOT incorrect type %d\n",
|
||||
objectId, (int)objType );
|
||||
return 0;
|
||||
}
|
||||
L2Player *cha = chars_array[index];
|
||||
if( !cha )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnAddObject(): player found in WOT, but is NULL in array? O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
if( cha->isUnused() )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnAddObject(): player is unused in array! O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ok, adding
|
||||
bool isEnemy = false;
|
||||
bool is2sidewar = false;
|
||||
TCHAR colText[128] = {0};
|
||||
TCHAR szBuf1[128] = {0};
|
||||
TCHAR szBuf2[128] = {0};
|
||||
|
||||
// detect clan war
|
||||
utils_detectClanWar( cha->relation, &isEnemy, &is2sidewar );
|
||||
|
||||
// name
|
||||
lstrcpy( colText, cha->getName() );
|
||||
int iImage = -1;
|
||||
if( isEnemy )
|
||||
{
|
||||
iImage = 0;
|
||||
if( !is2sidewar ) iImage = 3;
|
||||
}
|
||||
if( g_game_client->ai.party.isInParty( cha->objectID, NULL ) ) iImage = 1;
|
||||
if( cha->isAlikeDead ) iImage = 2;
|
||||
int added_item = -1;
|
||||
int added_item2 = -1;
|
||||
added_item = WULV_InsertItem2( g_rw_hWndCL, colText, 999, iImage, (LPARAM)cha->objectID );
|
||||
if( added_item == -1 ) return 0;
|
||||
if( isEnemy ) // add enemies also to enemies tab
|
||||
added_item2 = WULV_InsertItem2( g_rw_hWndEnemies, colText, 999, iImage, (LPARAM)cha->objectID );
|
||||
|
||||
// baseClass
|
||||
szBuf2[0] = szBuf1[0] = 0;
|
||||
cha->getClassStr( szBuf1 );
|
||||
if( cha->classID != cha->baseClassID )
|
||||
{
|
||||
cha->getBaseClassStr( szBuf2 );
|
||||
wsprintfW( colText, L"%s / %s", szBuf1, szBuf2 );
|
||||
}
|
||||
else wsprintfW( colText, L"%s", szBuf1 );
|
||||
WULV_SetItem( g_rw_hWndCL, colText, added_item, 1 );
|
||||
if( isEnemy ) // add enemies info also to enemies tab
|
||||
WULV_SetItem( g_rw_hWndEnemies, colText, added_item2, 1 );
|
||||
|
||||
// clan
|
||||
ClanList_GetClanNameByID( cha->clanID, colText ); // max 127 chars
|
||||
WULV_SetItem( g_rw_hWndCL, colText, added_item, 2 );
|
||||
if( isEnemy ) // add enemies info also to enemies tab
|
||||
WULV_SetItem( g_rw_hWndEnemies, colText, added_item2, 2 );
|
||||
|
||||
// dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - cha->z) );
|
||||
WULV_SetItem( g_rw_hWndCL, colText, added_item, 3 );
|
||||
if( isEnemy ) // add enemies info also to enemies tab
|
||||
WULV_SetItem( g_rw_hWndEnemies, colText, added_item2, 3 );
|
||||
|
||||
// clanwar state
|
||||
colText[0] = 0;
|
||||
if( isEnemy && !is2sidewar ) lstrcpy( colText, TEXT("<") );
|
||||
if( isEnemy && is2sidewar ) lstrcpy( colText, TEXT("<>") );
|
||||
WULV_SetItem( g_rw_hWndCL, colText, added_item, 4 );
|
||||
if( isEnemy ) // add enemies info also to enemies tab
|
||||
WULV_SetItem( g_rw_hWndEnemies, colText, added_item2, 4 );
|
||||
} break;
|
||||
|
||||
case MSG_NPC:
|
||||
{
|
||||
if( g_radarwnd_npc_displayEnable == 0 ) return 0; // NPC display disabled
|
||||
if( objType != L2OT_NPC )
|
||||
{
|
||||
log_error( LOG_WARNING, "RW_OnAddObject(): object [%u]: adding NPC, but in WOT incorrect type %d\n",
|
||||
objectId, (int)objType );
|
||||
return 0;
|
||||
}
|
||||
|
||||
L2Npc *npc = npc_array[index];
|
||||
if( !npc )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnAddObject(): NPC found in WOT, but is NULL in array? O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
if( npc->isUnused() )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnAddObject(): NPC is unused in array! O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TCHAR colText[128] = {0};
|
||||
wchar_t wName[128] = {0}; char aname[128] = {0};
|
||||
wchar_t wTitle[128] = {0}; char atitle[128] = {0};
|
||||
|
||||
// NPC name
|
||||
aname[0] = atitle[0] = 0;
|
||||
wName[0] = wTitle[0] = 0;
|
||||
lstrcpy( colText, npc->getName() );
|
||||
if( colText[0] == 0 )
|
||||
{
|
||||
if( L2Data_DB_GetNPCNameTitleByID( npc->templateID, aname, atitle ) )
|
||||
{
|
||||
MultiByteToWideChar( CP_ACP, 0, aname, -1, wName, 127 );
|
||||
MultiByteToWideChar( CP_ACP, 0, atitle, -1, wTitle, 127 );
|
||||
npc->setName( wName );
|
||||
lstrcpy( colText, wName );
|
||||
}
|
||||
}
|
||||
int iImage = -1;
|
||||
if( npc->isAlikeDead ) iImage = 2;
|
||||
int added_item = WULV_InsertItem2( g_rw_hWndNPC, colText, 999, iImage, (LPARAM)npc->objectID );
|
||||
if( added_item == -1 ) return 0;
|
||||
|
||||
// NPC title
|
||||
wcscpy( colText, npc->getTitle() );
|
||||
if( (colText[0] == 0) && (wTitle[0]) )
|
||||
{
|
||||
lstrcpy( colText, wTitle );
|
||||
npc->setTitle( wTitle );
|
||||
}
|
||||
WULV_SetItem( g_rw_hWndNPC, colText, added_item, 1 );
|
||||
|
||||
// NPC dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - npc->z) );
|
||||
WULV_SetItem( g_rw_hWndNPC, colText, added_item, 2 );
|
||||
|
||||
// NPC templateID
|
||||
wsprintf( colText, TEXT("%d"), npc->templateID );
|
||||
WULV_SetItem( g_rw_hWndNPC, colText, added_item, 3 );
|
||||
} break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LRESULT RW_OnUpdObject( HWND hWnd, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hWnd);
|
||||
// do not update npc if not displaying
|
||||
if( wParam == MSG_NPC && !g_radarwnd_npc_displayEnable ) return 0;
|
||||
|
||||
unsigned int objectId = (unsigned int)lParam;
|
||||
L2OBJECT_TYPE objType = L2OT_NONE;
|
||||
int index = -1;
|
||||
if( !WorldObjectTree_GetInfoByObjectID( objectId, &objType, &index ) )
|
||||
{
|
||||
log_error( LOG_WARNING, "RW_OnUpdObject(): cannot get info about object [%u] to add\n", objectId );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_z = g_game_client->ai.usr.z;
|
||||
|
||||
HWND hWndLV = g_rw_hWndCL; // default: from char list
|
||||
if( wParam == MSG_NPC ) hWndLV = g_rw_hWndNPC;
|
||||
|
||||
// find listview itemId to update
|
||||
int iItem = -1;
|
||||
LVITEM lvi;
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
int idx = -1;
|
||||
do
|
||||
{
|
||||
idx = ListView_GetNextItem( hWndLV, idx, LVNI_ALL );
|
||||
if( idx == -1 ) break;
|
||||
lvi.iItem = idx;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_PARAM;
|
||||
if( ListView_GetItem( hWndLV, &lvi ) )
|
||||
{
|
||||
if( ((unsigned int)lvi.lParam) == objectId )
|
||||
{
|
||||
iItem = lvi.iItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while( idx >= 0 );
|
||||
|
||||
if( iItem == -1 )
|
||||
{
|
||||
// not found
|
||||
switch( wParam )
|
||||
{
|
||||
case MSG_PC: log_error( LOG_WARNING, "RW_OnUpdObject(): cannot find player objectId [%u] in LV to update\n", objectId ); break;
|
||||
case MSG_NPC: log_error( LOG_WARNING, "RW_OnUpdObject(): cannot find NPC objectId [%u] in LV to update\n", objectId ); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.iItem = iItem;
|
||||
lvi.lParam = (LPARAM)objectId;
|
||||
switch( wParam )
|
||||
{
|
||||
case MSG_PC:
|
||||
{
|
||||
if( objType != L2OT_PC )
|
||||
{
|
||||
log_error( LOG_WARNING, "RW_OnUpdObject(): object [%u]: update player, but in WOT incorrect type %d\n",
|
||||
objectId, (int)objType );
|
||||
return 0;
|
||||
}
|
||||
L2Player *cha = chars_array[index];
|
||||
if( !cha )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnUpdObject(): player found in WOT, but is NULL in array? O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
if( cha->isUnused() )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnUpdObject(): player is unused in array! O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ok, adding
|
||||
bool isEnemy = false;
|
||||
bool is2sidewar = false;
|
||||
TCHAR colText[128] = {0};
|
||||
TCHAR szBuf1[128] = {0};
|
||||
TCHAR szBuf2[128] = {0};
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.cchTextMax = 128;
|
||||
lvi.pszText = colText;
|
||||
|
||||
// detect clan war
|
||||
utils_detectClanWar( cha->relation, &isEnemy, &is2sidewar );
|
||||
|
||||
// name
|
||||
lstrcpy( colText, cha->getName() );
|
||||
lvi.pszText = colText;
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = cha->objectID;
|
||||
// image
|
||||
lvi.iImage = -1;
|
||||
if( isEnemy )
|
||||
{
|
||||
lvi.iImage = 0; // RED CIRC
|
||||
if( !is2sidewar ) lvi.iImage = 3; // HALF RED CIRC
|
||||
}
|
||||
if( g_game_client->ai.party.isInParty( cha->objectID, NULL ) ) lvi.iImage = 1;
|
||||
if( cha->isAlikeDead ) lvi.iImage = 2;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
lvi.iImage = 0;
|
||||
|
||||
// baseClass
|
||||
szBuf2[0] = szBuf1[0] = 0;
|
||||
cha->getClassStr( szBuf1 );
|
||||
if( cha->classID != cha->baseClassID )
|
||||
{
|
||||
cha->getBaseClassStr( szBuf2 );
|
||||
wsprintfW( colText, L"%s / %s", szBuf1, szBuf2 );
|
||||
}
|
||||
else wsprintfW( colText, L"%s", szBuf1 );
|
||||
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 1;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// clan
|
||||
ClanList_GetClanNameByID( cha->clanID, colText ); // max 127 chars
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 2;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - cha->z) );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 3;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// clanwar state
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 4;
|
||||
lvi.pszText = colText;
|
||||
if( isEnemy )
|
||||
{
|
||||
colText[0] = 0;
|
||||
if( !is2sidewar ) lstrcpy( colText, TEXT("<") );
|
||||
if( is2sidewar ) lstrcpy( colText, TEXT("<>") );
|
||||
}
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// update enemies also in enemies list
|
||||
if( isEnemy ) RW_UpdateCharInEnemiesList( cha );
|
||||
} break;
|
||||
|
||||
case MSG_NPC:
|
||||
{
|
||||
L2Npc *npc = npc_array[index];
|
||||
if( !npc )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnUpdObject(): NPC found in WOT, but is NULL in array? O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
if( npc->isUnused() )
|
||||
{
|
||||
log_error( LOG_ERROR, "RW_OnUpdObject(): NPC is unused in array! O_o\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TCHAR colText[128] = {0};
|
||||
wchar_t wName[128] = {0}; char aname[128] = {0};
|
||||
wchar_t wTitle[128] = {0}; char atitle[128] = {0};
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.cchTextMax = 128;
|
||||
lvi.pszText = colText;
|
||||
|
||||
// NPC name
|
||||
aname[0] = atitle[0] = 0;
|
||||
wName[0] = wTitle[0] = 0;
|
||||
lstrcpy( colText, npc->getName() );
|
||||
if( colText[0] == 0 )
|
||||
{
|
||||
if( L2Data_DB_GetNPCNameTitleByID( npc->templateID, aname, atitle ) )
|
||||
{
|
||||
MultiByteToWideChar( CP_ACP, 0, aname, -1, wName, 127 );
|
||||
MultiByteToWideChar( CP_ACP, 0, atitle, -1, wTitle, 127 );
|
||||
npc->setName( wName );
|
||||
lstrcpy( colText, wName );
|
||||
}
|
||||
}
|
||||
lvi.pszText = colText;
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = npc->objectID;
|
||||
lvi.iImage = -1;
|
||||
if( npc->isAlikeDead ) lvi.iImage = 2;
|
||||
//log_error_np( LOG_OK, "Updating NPC %S, setting iImage = %d\n", npc->charName, lvi.iImage );
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
lvi.iImage = 0;
|
||||
|
||||
// NPC title
|
||||
wcscpy( colText, npc->getTitle() );
|
||||
if( (colText[0] == 0) && (wTitle[0]) )
|
||||
{
|
||||
lstrcpy( colText, wTitle );
|
||||
npc->setTitle( wTitle );
|
||||
}
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 1;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// NPC dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - npc->z) );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 2;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// NPC templateID
|
||||
wsprintf( colText, TEXT("%d"), npc->templateID );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 3;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
} break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LRESULT RW_OnDelObject( HWND hWnd, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hWnd);
|
||||
// do not del npc if do not display
|
||||
if( wParam == MSG_NPC && !g_radarwnd_npc_displayEnable ) return 0;
|
||||
|
||||
bool deleteOK = false;
|
||||
HWND hWndLV = g_rw_hWndCL; // by default: delete from PC list
|
||||
if( wParam == MSG_NPC ) hWndLV = g_rw_hWndNPC; // if NPC, delete from NPC list
|
||||
unsigned int objectId = (unsigned int)lParam;
|
||||
LVITEM lvi;
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
|
||||
int idx = -1;
|
||||
do
|
||||
{
|
||||
idx = ListView_GetNextItem( hWndLV, idx, LVNI_ALL );
|
||||
if( idx == -1 ) break;
|
||||
lvi.iItem = idx;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_PARAM;
|
||||
if( ListView_GetItem( hWndLV, &lvi ) )
|
||||
{
|
||||
if( ((unsigned int)lvi.lParam) == objectId )
|
||||
{
|
||||
ListView_DeleteItem( hWndLV, lvi.iItem );
|
||||
deleteOK = true;
|
||||
if( wParam == MSG_NPC ) return 0;
|
||||
if( wParam == MSG_PC ) break;
|
||||
}
|
||||
}
|
||||
} while( idx >= 0 );
|
||||
|
||||
if( deleteOK )
|
||||
{
|
||||
// delete also enemies from enemies list (if enemy)
|
||||
if( wParam == MSG_PC )
|
||||
{
|
||||
//log_error( LOG_OK, "RW_OnDelObject(): MSG_PC: deleting PC\n" );
|
||||
//unsigned int RELATION_MUTUAL_WAR = 0x08000;
|
||||
//unsigned int RELATION_1SIDED_WAR = 0x10000;
|
||||
//if( g_cfg.L2_version == L2_VERSION_T23 )
|
||||
//{
|
||||
// RELATION_MUTUAL_WAR = 0x04000; // gracia final constants changed
|
||||
// RELATION_1SIDED_WAR = 0x08000;
|
||||
//}
|
||||
//L2OBJECT_TYPE objType = L2OT_NONE;
|
||||
//int index = -1;
|
||||
//if( WorldObjectTree_GetInfoByObjectID( objectId, &objType, &index ) )
|
||||
//{
|
||||
// int relation = chars_array[index]->relation;
|
||||
// log_error( LOG_OK, "RW_OnDelObject(): MSG_PC: deleting PC %S relation 0x%08X\n",
|
||||
// chars_array[index]->charName, chars_array[index]->relation );
|
||||
// if( (relation & RELATION_1SIDED_WAR) || (relation & RELATION_MUTUAL_WAR) )
|
||||
RW_DeleteCharFromEnemiesList( objectId );
|
||||
//}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if we here, objectId not found
|
||||
log_error( LOG_WARNING, "RW_OnDelObject(): cannot find oid [%u] in List-View\n", objectId );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RW_DeleteCharFromEnemiesList( unsigned int objectID )
|
||||
{
|
||||
LVITEM lvi;
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
|
||||
int idx = -1;
|
||||
do
|
||||
{
|
||||
idx = ListView_GetNextItem( g_rw_hWndEnemies, idx, LVNI_ALL );
|
||||
if( idx == -1 ) break;
|
||||
lvi.iItem = idx;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_PARAM;
|
||||
if( ListView_GetItem( g_rw_hWndEnemies, &lvi ) )
|
||||
{
|
||||
if( ((unsigned int)lvi.lParam) == objectID )
|
||||
{
|
||||
ListView_DeleteItem( g_rw_hWndEnemies, lvi.iItem );
|
||||
log_error( LOG_OK, "RW_DeleteCharFromEnemiesList(): oid [%u] del OK\n", objectID );
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while( idx >= 0 );
|
||||
|
||||
// if we here, objectId not found
|
||||
// this is not error
|
||||
//log_error( LOG_WARNING, "RW_DeleteCharFromEnemiesList(): cannot find char oid [%u] in List-View\n",
|
||||
// cha->objectID, cha->charName );
|
||||
return;
|
||||
}
|
||||
|
||||
void RW_UpdateCharInEnemiesList( L2Player *cha )
|
||||
{
|
||||
int user_z = g_game_client->ai.usr.z;
|
||||
|
||||
// find listview itemId to update
|
||||
int iItem = -1;
|
||||
LVITEM lvi;
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
int idx = -1;
|
||||
do
|
||||
{
|
||||
idx = ListView_GetNextItem( g_rw_hWndEnemies, idx, LVNI_ALL );
|
||||
if( idx == -1 ) break;
|
||||
lvi.iItem = idx;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_PARAM;
|
||||
if( ListView_GetItem( g_rw_hWndEnemies, &lvi ) )
|
||||
{
|
||||
if( ((unsigned int)lvi.lParam) == cha->objectID )
|
||||
{
|
||||
iItem = lvi.iItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while( idx >= 0 );
|
||||
|
||||
if( iItem == -1 )
|
||||
{
|
||||
// not found
|
||||
log_error( LOG_WARNING, "RW_UpdateCharInEnemiesList(): cannot find objectId [%u] in Enemies LV to update\n",
|
||||
cha->objectID );
|
||||
return;
|
||||
}
|
||||
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.iItem = iItem;
|
||||
lvi.lParam = (LPARAM)(cha->objectID);
|
||||
|
||||
// ok, adding
|
||||
bool isEnemy = false;
|
||||
bool is2sidewar = false;
|
||||
TCHAR colText[128] = {0};
|
||||
TCHAR szBuf1[128] = {0};
|
||||
TCHAR szBuf2[128] = {0};
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.cchTextMax = 128;
|
||||
lvi.pszText = colText;
|
||||
|
||||
// detect clan war
|
||||
utils_detectClanWar( cha->relation, &isEnemy, &is2sidewar );
|
||||
|
||||
// name
|
||||
lstrcpy( colText, cha->getName() );
|
||||
lvi.pszText = colText;
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = cha->objectID;
|
||||
// image
|
||||
lvi.iImage = -1;
|
||||
if( isEnemy )
|
||||
{
|
||||
lvi.iImage = 0;
|
||||
if( !is2sidewar ) lvi.iImage = 3;
|
||||
}
|
||||
if( g_game_client->ai.party.isInParty( cha->objectID, NULL ) ) lvi.iImage = 1;
|
||||
if( cha->isAlikeDead ) lvi.iImage = 2;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
lvi.iImage = 0;
|
||||
|
||||
// baseClass
|
||||
szBuf2[0] = szBuf1[0] = 0;
|
||||
cha->getClassStr( szBuf1 );
|
||||
if( cha->classID != cha->baseClassID )
|
||||
{
|
||||
cha->getBaseClassStr( szBuf2 );
|
||||
wsprintfW( colText, L"%s / %s", szBuf1, szBuf2 );
|
||||
}
|
||||
else wsprintfW( colText, L"%s", szBuf1 );
|
||||
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 1;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// clan
|
||||
ClanList_GetClanNameByID( cha->clanID, colText ); // max 127 chars
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 2;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - cha->z) );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 3;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
|
||||
// clanwar state
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = iItem;
|
||||
lvi.iSubItem = 4;
|
||||
lvi.pszText = colText;
|
||||
if( isEnemy )
|
||||
{
|
||||
colText[0] = 0;
|
||||
if( !is2sidewar ) lstrcpy( colText, TEXT("<") );
|
||||
if( is2sidewar ) lstrcpy( colText, TEXT("<>") );
|
||||
}
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEMTEXT, (WPARAM)iItem, (LPARAM)&lvi );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RadarWnd_ForceUpdateCharsList()
|
||||
{
|
||||
PostMessage( g_radardll_hwnd, WMMY_FORCE_UPDATE_LIST, FORCE_UPDATE_CHARS_LIST, 0 );
|
||||
}
|
||||
|
||||
void RadarWnd_ForceUpdateNpcsList()
|
||||
{
|
||||
PostMessage( g_radardll_hwnd, WMMY_FORCE_UPDATE_LIST, FORCE_UPDATE_NPCS_LIST, 0 );
|
||||
}
|
||||
|
||||
LRESULT RW_OnUpdateCharsList( HWND hWnd )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hWnd);
|
||||
// window is visible?
|
||||
//if( bRadarWindowIsVisible == FALSE ) return 0;
|
||||
// check too fast updates timeout
|
||||
//DWORD dwCurTickTime = GetTickCount();
|
||||
//if( dwCurTickTime < (dwRadarDllLastCharListUpdateTime + 1000) ) return 0;
|
||||
//dwRadarDllLastCharListUpdateTime = dwCurTickTime;
|
||||
// IN_GAME?
|
||||
//if( g_game_client->getState() != GCST_IN_GAME ) return 0;
|
||||
// delete all items from list-view
|
||||
SendMessage( g_rw_hWndCL, LVM_DELETEALLITEMS, 0, 0 );
|
||||
// delete all items from enemies list-view
|
||||
SendMessage( g_rw_hWndEnemies, LVM_DELETEALLITEMS, 0, 0 );
|
||||
//
|
||||
int user_z;
|
||||
user_z = g_game_client->ai.usr.z;
|
||||
int i;
|
||||
TCHAR colText[128] = {0};
|
||||
TCHAR szBuf1[128] = {0};
|
||||
TCHAR szBuf2[128] = {0};
|
||||
LVITEM lvi;
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.cchTextMax = 128;
|
||||
lvi.pszText = colText;
|
||||
bool isEnemy = false;
|
||||
bool is2sidewar = false;
|
||||
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
|
||||
{
|
||||
L2Player *cha = chars_array[i];
|
||||
if( !cha ) continue;
|
||||
if( cha->isUnused() ) continue;
|
||||
isEnemy = false;
|
||||
is2sidewar = false;
|
||||
utils_detectClanWar( cha->relation, &isEnemy, &is2sidewar );
|
||||
// name
|
||||
lstrcpy( colText, cha->getName() );
|
||||
lvi.pszText = colText;
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||||
lvi.iItem = 999;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = cha->objectID;
|
||||
// image
|
||||
lvi.iImage = -1;
|
||||
if( isEnemy )
|
||||
{
|
||||
lvi.iImage = 0;
|
||||
if( !is2sidewar ) lvi.iImage = 3;
|
||||
}
|
||||
if( g_game_client->ai.party.isInParty( cha->objectID, NULL ) ) lvi.iImage = 1;
|
||||
if( cha->isAlikeDead ) lvi.iImage = 2;
|
||||
int added_item = -1;
|
||||
int added_item2 = -1;
|
||||
added_item = (int)SendMessage( g_rw_hWndCL, LVM_INSERTITEM, 0, (LPARAM)&lvi );
|
||||
if( added_item == -1 ) continue;
|
||||
if( isEnemy )
|
||||
{
|
||||
// add enemies also to enemies tab
|
||||
added_item2 = (int)SendMessage( g_rw_hWndEnemies, LVM_INSERTITEM, 0, (LPARAM)&lvi );
|
||||
}
|
||||
lvi.iImage = 0;
|
||||
|
||||
// baseClass
|
||||
#ifdef UNICODE
|
||||
szBuf2[0] = szBuf1[0] = 0;
|
||||
cha->getClassStr( szBuf1 );
|
||||
if( cha->classID != cha->baseClassID )
|
||||
{
|
||||
cha->getBaseClassStr( szBuf2 );
|
||||
wsprintfW( colText, L"%s / %s", szBuf1, szBuf2 );
|
||||
}
|
||||
else wsprintfW( colText, L"%s", szBuf1 );
|
||||
#else
|
||||
//wsprintfA( colText, "%s/%s", cha->classStr(), cha->baseClassStr() );
|
||||
#endif
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 1;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
if( isEnemy )
|
||||
{
|
||||
// add enemies info also to enemies tab
|
||||
lvi.iItem = added_item2;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
}
|
||||
|
||||
// clan
|
||||
ClanList_GetClanNameByID( cha->clanID, colText ); // max 127 chars
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 2;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
if( isEnemy )
|
||||
{
|
||||
// add enemies info also to enemies tab
|
||||
lvi.iItem = added_item2;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
}
|
||||
|
||||
// dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - cha->z) );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 3;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
if( isEnemy )
|
||||
{
|
||||
// add enemies info also to enemies tab
|
||||
lvi.iItem = added_item2;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
}
|
||||
|
||||
// clanwar state
|
||||
if( isEnemy )
|
||||
{
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 4;
|
||||
lvi.pszText = colText;
|
||||
colText[0] = 0;
|
||||
if( isEnemy && !is2sidewar ) lstrcpy( colText, TEXT("<") );
|
||||
if( isEnemy && is2sidewar ) lstrcpy( colText, TEXT("<>") );
|
||||
if( colText[0] )
|
||||
{
|
||||
SendMessage( g_rw_hWndCL, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
// add enemies info also to enemies tab
|
||||
lvi.iItem = added_item2;
|
||||
SendMessage( g_rw_hWndEnemies, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT RW_OnUpdateNpcsList( HWND hWnd )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hWnd);
|
||||
// in game?
|
||||
if( g_game_client->getState() != GCST_IN_GAME ) return 0;
|
||||
// clear ListView
|
||||
SendMessage( g_rw_hWndNPC, LVM_DELETEALLITEMS, 0, 0 );
|
||||
if( g_radarwnd_npc_displayEnable == 0 ) return 0;
|
||||
//
|
||||
int user_z;
|
||||
user_z = g_game_client->ai.usr.z;
|
||||
int i;
|
||||
TCHAR colText[128] = {0};
|
||||
wchar_t wName[128] = {0}; char aname[128] = {0};
|
||||
wchar_t wTitle[128] = {0}; char atitle[128] = {0};
|
||||
LVITEM lvi;
|
||||
memset( &lvi, 0, sizeof(lvi) );
|
||||
lvi.cchTextMax = 128;
|
||||
lvi.pszText = colText;
|
||||
for( i=0; i<NPCA_MAX_NPCS; i++ )
|
||||
{
|
||||
//
|
||||
aname[0] = atitle[0] = 0;
|
||||
wName[0] = wTitle[0] = 0;
|
||||
//
|
||||
L2Npc *npc = npc_array[i];
|
||||
if( !npc ) continue;
|
||||
if( npc->isUnused() ) continue;
|
||||
// name
|
||||
lstrcpy( colText, npc->getName() );
|
||||
if( colText[0] == 0 )
|
||||
{
|
||||
if( L2Data_DB_GetNPCNameTitleByID( npc->templateID, aname, atitle ) )
|
||||
{
|
||||
MultiByteToWideChar( CP_ACP, 0, aname, -1, wName, 127 );
|
||||
MultiByteToWideChar( CP_ACP, 0, atitle, -1, wTitle, 127 );
|
||||
npc->setName( wName );
|
||||
//npc->setTitle( wTitle );
|
||||
lstrcpy( colText, wName );
|
||||
}
|
||||
}
|
||||
lvi.pszText = colText;
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||||
lvi.iItem = 999;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = npc->objectID;
|
||||
lvi.iImage = -1;
|
||||
if( npc->isAlikeDead ) lvi.iImage = 2;
|
||||
int added_item = (int)SendMessage( g_rw_hWndNPC, LVM_INSERTITEM, 0, (LPARAM)&lvi );
|
||||
if( added_item == -1 ) continue;
|
||||
lvi.iImage = 0;
|
||||
|
||||
// title
|
||||
#ifdef UNICODE
|
||||
wcscpy( colText, npc->getTitle() );
|
||||
if( (colText[0] == 0) && (wTitle[0]) )
|
||||
{
|
||||
lstrcpy( colText, wTitle );
|
||||
npc->setTitle( wTitle );
|
||||
}
|
||||
#else
|
||||
wsprintfA( colText, "%S", npc->getTitle() );
|
||||
#endif
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 1;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
// dZ
|
||||
wsprintf( colText, TEXT("%d"), (user_z - npc->z) );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 2;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
// templateID
|
||||
wsprintf( colText, TEXT("%d"), npc->templateID );
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 3;
|
||||
lvi.pszText = colText;
|
||||
SendMessage( g_rw_hWndNPC, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
319
l2detect/RadarSetupDlg.cpp
Normal file
319
l2detect/RadarSetupDlg.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "ConfigIni.h"
|
||||
//#include "GameClient.h"
|
||||
#include "ConfigDlg.h"
|
||||
#include "Logger.h"
|
||||
// children
|
||||
#include "RadarSetupDlg_SelfHeal.h"
|
||||
#include "RadarSetupDlg_OffpartyBDSWS.h"
|
||||
#include "RadarSetupDlg_SoundAlerts.h"
|
||||
#include "RadarSetupDlg_Colors.h"
|
||||
#include "RadarSetupDlg_InvisGM.h"
|
||||
#include "RadarSetupDlg_QuickTarget.h"
|
||||
#include "RadarSetupDlg_LT.h"
|
||||
#include "RadarSetupDlg_FolAsi.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class CConfig g_cfg;
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
void RadarSetupDlgStart( HWND hWndParent )
|
||||
{
|
||||
DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SETUPRADAR), hWndParent, RadarSetupDlgProc, 0 );
|
||||
}
|
||||
|
||||
HWND rs_hwndTV;
|
||||
//HTREEITEM
|
||||
|
||||
// lParams
|
||||
#define L_HEAL_USEITEMS 1
|
||||
#define L_HEAL_USESKILL 2
|
||||
#define L_QUICK_TARGET 3
|
||||
#define L_LOCK_TARGET 4
|
||||
#define L_ASSIST_FOLLOW 5
|
||||
#define L_OFFPARTY_BDSWS 6
|
||||
#define L_SOUND_ALERTS 7
|
||||
#define L_COLORS 8
|
||||
#define L_INIVIS_GM 9
|
||||
|
||||
#define RS_CHILD_COUNT 9
|
||||
HWND radarSetupDlg_children[ RS_CHILD_COUNT + 1 ];
|
||||
|
||||
void RadarSetupDlg_OnInitDialog( HWND hDlg );
|
||||
void RadarSetupDlg_OnOK( HWND hDlg );
|
||||
void RadarSetupDlg_OnCancel( HWND hDlg );
|
||||
void RadarSetupDlg_OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam );
|
||||
void RadarSetupDlg_OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam );
|
||||
void RadarSetupDlg_OnTreeViewSelChanging( HWND hDlg, LPARAM lParam );
|
||||
void RadarSetupDlg_OnTreeViewSelChanged( HWND hDlg, LPARAM lParam );
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: RadarSetupDlg_OnInitDialog( hDlg ); break;
|
||||
case WM_COMMAND: RadarSetupDlg_OnCommand( hDlg, wParam, lParam ); break;
|
||||
case WM_NOTIFY: RadarSetupDlg_OnNotify( hDlg, wParam, lParam ); break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnInitDialog_InitTreeView( HWND hDlg )
|
||||
{
|
||||
rs_hwndTV = GetDlgItem( hDlg, IDC_T_CONFIG );
|
||||
TCHAR text[256] = {0};
|
||||
HTREEITEM htiHealing = NULL;
|
||||
HTREEITEM htiParty = NULL;
|
||||
HTREEITEM htiTargets = NULL;
|
||||
HTREEITEM htiLookAndFeel = NULL;
|
||||
HTREEITEM htiHacks = NULL;
|
||||
TVINSERTSTRUCT tvis;
|
||||
// insert at root
|
||||
tvis.hParent = NULL;
|
||||
tvis.hInsertAfter = TVI_LAST;
|
||||
tvis.item.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
|
||||
tvis.item.stateMask = TVIS_BOLD | TVIS_EXPANDED;
|
||||
// insert Healing
|
||||
tvis.item.lParam = 0;
|
||||
tvis.item.cChildren = 1;
|
||||
tvis.item.state = TVIS_BOLD | TVIS_EXPANDED;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Self") );
|
||||
htiHealing = TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
// insert Party
|
||||
tvis.item.lParam = 0;
|
||||
tvis.item.cChildren = 1;
|
||||
tvis.item.state = TVIS_BOLD | TVIS_EXPANDED;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Party") );
|
||||
htiParty = TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
// insert Targeting
|
||||
tvis.item.lParam = 0;
|
||||
tvis.item.cChildren = 1;
|
||||
tvis.item.state = TVIS_BOLD | TVIS_EXPANDED;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("PvP settings") );
|
||||
htiTargets = TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
// insert LookAndFeel
|
||||
tvis.item.lParam = 0;
|
||||
tvis.item.cChildren = 1;
|
||||
tvis.item.state = TVIS_BOLD | TVIS_EXPANDED;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Look And Feel") );
|
||||
htiLookAndFeel = TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
// insert hacks
|
||||
tvis.item.lParam = 0;
|
||||
tvis.item.cChildren = 1;
|
||||
tvis.item.state = TVIS_BOLD | TVIS_EXPANDED;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Hacks!") );
|
||||
htiHacks = TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
|
||||
// insert children
|
||||
// insert Healing children
|
||||
tvis.hParent = htiHealing;
|
||||
tvis.hInsertAfter = TVI_LAST;
|
||||
//
|
||||
tvis.item.lParam = L_HEAL_USEITEMS;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Heal Use Items") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
tvis.item.lParam = L_HEAL_USESKILL;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Heal Use Skills") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
// insert Party children
|
||||
tvis.hParent = htiParty;
|
||||
tvis.hInsertAfter = TVI_LAST;
|
||||
//
|
||||
tvis.item.lParam = L_OFFPARTY_BDSWS;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Offparty dance/song") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
// insert Targets children
|
||||
tvis.hParent = htiTargets;
|
||||
tvis.hInsertAfter = TVI_LAST;
|
||||
//
|
||||
tvis.item.lParam = L_QUICK_TARGET;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Quick targeting") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
tvis.item.lParam = L_LOCK_TARGET;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Lock target") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
tvis.item.lParam = L_ASSIST_FOLLOW;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Assist & follow") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
// insert LookAndFeel children
|
||||
tvis.hParent = htiLookAndFeel;
|
||||
tvis.hInsertAfter = TVI_LAST;
|
||||
// insert colors
|
||||
tvis.item.lParam = L_COLORS;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Colors") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
// insert Sound Alerts
|
||||
tvis.item.lParam = L_SOUND_ALERTS;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Sound Alerts") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
//
|
||||
// insert Hacks children
|
||||
tvis.hParent = htiHacks;
|
||||
tvis.hInsertAfter = TVI_LAST;
|
||||
//
|
||||
tvis.item.lParam = L_INIVIS_GM;
|
||||
tvis.item.cChildren = 0;
|
||||
tvis.item.state = 0;
|
||||
tvis.item.pszText = text;
|
||||
lstrcpy( text, TEXT("Invisible objects detection") );
|
||||
TreeView_InsertItem( rs_hwndTV, &tvis );
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnInitDialog_InitChildren( HWND hDlg )
|
||||
{
|
||||
RECT r, rd;
|
||||
int tree_x = 0;
|
||||
int tree_w = 0;
|
||||
int right_w = 0;
|
||||
int h = 0;
|
||||
HWND htv = GetDlgItem( hDlg, IDC_T_CONFIG );
|
||||
GetWindowRect( htv, &r );
|
||||
GetClientRect( hDlg, &rd );
|
||||
tree_x = 20;
|
||||
tree_w = r.right - r.left;
|
||||
right_w = rd.right - rd.left - tree_w - tree_x - 10;
|
||||
h = r.bottom - r.top;
|
||||
int i;
|
||||
radarSetupDlg_children[0] = 0;
|
||||
radarSetupDlg_children[L_HEAL_USEITEMS] = RadarSetupDlg_SelfHeal_Create( hDlg );
|
||||
radarSetupDlg_children[L_HEAL_USESKILL] = NULL; // TODO
|
||||
radarSetupDlg_children[L_OFFPARTY_BDSWS] = RadarSetupDlg_OFFBDSWS_Create( hDlg );
|
||||
radarSetupDlg_children[L_QUICK_TARGET] = RadarSetupDlg_QuickTarget_Create( hDlg );
|
||||
radarSetupDlg_children[L_LOCK_TARGET] = RadarSetupDlg_LockTarget_Create( hDlg );
|
||||
radarSetupDlg_children[L_ASSIST_FOLLOW] = RadarSetupDlg_FolAsi_Create( hDlg ); // TODO
|
||||
radarSetupDlg_children[L_SOUND_ALERTS] = RadarSetupDlg_SoundAlerts_Create( hDlg );
|
||||
radarSetupDlg_children[L_COLORS] = RadarSetupDlg_Colors_Create( hDlg );
|
||||
radarSetupDlg_children[L_INIVIS_GM] = RadarSetupDlg_InvisGM_Create( hDlg );
|
||||
// fix windows
|
||||
//DWORD dwStyle;
|
||||
for( i=1; i<=RS_CHILD_COUNT; i++ )
|
||||
{
|
||||
//dwStyle = GetWindowLongPtr( radarSetupDlg_children[i], GWL_STYLE );
|
||||
//dwStyle |= WS_CHILD;
|
||||
//SetWindowLongPtr( radarSetupDlg_children[i], GWL_STYLE, (LONG)dwStyle );
|
||||
MoveWindow( radarSetupDlg_children[i], tree_x + tree_w + 5, 5, right_w, h, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnInitDialog_DestroyChildren()
|
||||
{
|
||||
int i = RS_CHILD_COUNT;
|
||||
while( i>0 )
|
||||
{
|
||||
if( radarSetupDlg_children[i] )
|
||||
{
|
||||
SendMessage( radarSetupDlg_children[i], WM_COMMAND, IDC_APPLY, 0 );
|
||||
DestroyWindow( radarSetupDlg_children[i] );
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnInitDialog( HWND hDlg )
|
||||
{
|
||||
RadarSetupDlg_OnInitDialog_InitChildren( hDlg );
|
||||
RadarSetupDlg_OnInitDialog_InitTreeView( hDlg );
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnOK( HWND hDlg )
|
||||
{
|
||||
RadarSetupDlg_OnInitDialog_DestroyChildren();
|
||||
EndDialog( hDlg, IDOK );
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnCancel( HWND hDlg )
|
||||
{
|
||||
RadarSetupDlg_OnInitDialog_DestroyChildren();
|
||||
EndDialog( hDlg, IDOK );
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnTreeViewSelChanging( HWND hDlg, LPARAM lParam )
|
||||
{
|
||||
hDlg;
|
||||
LPNMTREEVIEW p = (LPNMTREEVIEW)lParam;
|
||||
int idx = (int)(p->itemOld.lParam);
|
||||
if( (idx >= 1) && (idx <= RS_CHILD_COUNT) )
|
||||
{
|
||||
if( radarSetupDlg_children[idx] )
|
||||
ShowWindow( radarSetupDlg_children[idx], SW_HIDE );
|
||||
}
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnTreeViewSelChanged( HWND hDlg, LPARAM lParam )
|
||||
{
|
||||
hDlg;
|
||||
LPNMTREEVIEW p = (LPNMTREEVIEW)lParam;
|
||||
int idx = (int)(p->itemNew.lParam);
|
||||
if( (idx >= 1) && (idx <= RS_CHILD_COUNT) )
|
||||
{
|
||||
if( radarSetupDlg_children[idx] )
|
||||
ShowWindow( radarSetupDlg_children[idx], SW_SHOW );
|
||||
}
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDOK: RadarSetupDlg_OnOK( hDlg ); break;
|
||||
case IDCANCEL: RadarSetupDlg_OnCancel( hDlg ); break;
|
||||
case IDC_NPSETUP: ConfigDialogStart( hDlg ); break;
|
||||
}
|
||||
}
|
||||
|
||||
void RadarSetupDlg_OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
wParam;
|
||||
LPNMHDR pnmh = (LPNMHDR)lParam;
|
||||
if( pnmh == NULL ) return;
|
||||
switch( pnmh->code )
|
||||
{
|
||||
case TVN_SELCHANGING:
|
||||
{
|
||||
if( pnmh->hwndFrom == rs_hwndTV ) RadarSetupDlg_OnTreeViewSelChanging( hDlg, lParam );
|
||||
} break;
|
||||
case TVN_SELCHANGED:
|
||||
{
|
||||
if( pnmh->hwndFrom == rs_hwndTV ) RadarSetupDlg_OnTreeViewSelChanged( hDlg, lParam );
|
||||
} break;
|
||||
}
|
||||
}
|
||||
6
l2detect/RadarSetupDlg.h
Normal file
6
l2detect/RadarSetupDlg.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RADARSETUPDLG
|
||||
#define H_RADARSETUPDLG
|
||||
|
||||
void RadarSetupDlgStart( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
140
l2detect/RadarSetupDlg_Colors.cpp
Normal file
140
l2detect/RadarSetupDlg_Colors.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "RadarDllWndCfg.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
// radar window UI config
|
||||
extern RADARWNDCFG g_rwCfg; // in RadarDllWndProc.cpp
|
||||
|
||||
INT_PTR CALLBACK Colors_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_Colors_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_COLORS),
|
||||
hWndParent, Colors_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
void Colors_Init( HWND hDlg );
|
||||
void Colors_OnDestroy( HWND hDlg );
|
||||
void Colors_OnApply( HWND hDlg );
|
||||
void Colors_OnPaint( HWND hDlg );
|
||||
void Colors_OnSelColor( HWND hDlg, int idx );
|
||||
|
||||
|
||||
INT_PTR CALLBACK Colors_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: Colors_Init( hDlg ); break;
|
||||
case WM_DESTROY: { Colors_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: Colors_OnApply( hDlg ); break;
|
||||
// colors
|
||||
case IDC_B_SELNPCCOLOR: Colors_OnSelColor( hDlg, 0 ); break;
|
||||
case IDC_B_SELMOBCOLOR: Colors_OnSelColor( hDlg, 1 ); break;
|
||||
case IDC_B_SELPLAYERCOLOR: Colors_OnSelColor( hDlg, 2 ); break;
|
||||
case IDC_B_SELDEADPLAYERCOLOR: Colors_OnSelColor( hDlg, 3 ); break;
|
||||
case IDC_B_SELPARTYPLAYERCOLOR: Colors_OnSelColor( hDlg, 4 ); break;
|
||||
case IDC_B_SELDEADPARTYPLAYERCOLOR: Colors_OnSelColor( hDlg, 5 ); break;
|
||||
case IDC_B_SELENEMYPLAYERCOLOR: Colors_OnSelColor( hDlg, 6 ); break;
|
||||
case IDC_B_SELDEADENEMYPLAYERCOLOR: Colors_OnSelColor( hDlg, 7 ); break;
|
||||
}
|
||||
} break;
|
||||
case WM_PAINT: Colors_OnPaint( hDlg ); break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Colors_Init( HWND hDlg )
|
||||
{
|
||||
hDlg;
|
||||
//log_error( LOG_OK, "Colors_Init\n" );
|
||||
}
|
||||
|
||||
|
||||
void Colors_OnDestroy( HWND hDlg )
|
||||
{
|
||||
hDlg;
|
||||
//log_error( LOG_OK, "Colors_OnDestroy\n" );
|
||||
}
|
||||
|
||||
void Colors_OnApply( HWND hDlg )
|
||||
{
|
||||
hDlg;
|
||||
//log_error( LOG_OK, "Colors_OnApply\n" );
|
||||
RadarWndCfg_SaveConfigToFile( &g_rwCfg, NULL );
|
||||
}
|
||||
|
||||
void Colors_OnPaint( HWND hDlg )
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
hdc = BeginPaint( hDlg, &ps );
|
||||
HPEN hPenPrev = (HPEN)SelectObject( hdc, GetStockObject( DC_PEN ) );
|
||||
HBRUSH hBrushPrev = (HBRUSH)SelectObject( hdc, GetStockObject( DC_BRUSH ) );
|
||||
//
|
||||
SetDCPenColor( hdc, RGB(0,0,0) );
|
||||
int i;
|
||||
for( i=0; i<8; i++ )
|
||||
{
|
||||
switch( i )
|
||||
{
|
||||
case 0: SetDCBrushColor( hdc, g_rwCfg.ui.colors.npcColor ); break;
|
||||
case 1: SetDCBrushColor( hdc, g_rwCfg.ui.colors.mobColor ); break;
|
||||
case 2: SetDCBrushColor( hdc, g_rwCfg.ui.colors.pcColor ); break;
|
||||
case 3: SetDCBrushColor( hdc, g_rwCfg.ui.colors.pcColorDead ); break;
|
||||
case 4: SetDCBrushColor( hdc, g_rwCfg.ui.colors.pcColorParty ); break;
|
||||
case 5: SetDCBrushColor( hdc, g_rwCfg.ui.colors.pcColorPartyDead ); break;
|
||||
case 6: SetDCBrushColor( hdc, g_rwCfg.ui.colors.pcColorWar ); break;
|
||||
case 7: SetDCBrushColor( hdc, g_rwCfg.ui.colors.pcColorWarDead ); break;
|
||||
}
|
||||
Rectangle( hdc, 240, 5 + i*21, 260, 5 + i*21+15 );
|
||||
}
|
||||
//
|
||||
SelectObject( hdc, (HGDIOBJ)hBrushPrev );
|
||||
SelectObject( hdc, (HGDIOBJ)hPenPrev );
|
||||
EndPaint( hDlg, &ps );
|
||||
}
|
||||
|
||||
COLORREF Colors_MyChooseColor( HWND hDlg, COLORREF in )
|
||||
{
|
||||
COLORREF init = in;
|
||||
COLORREF custColors[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
CHOOSECOLOR cc;
|
||||
memset( &cc, 0, sizeof(cc) );
|
||||
cc.lStructSize = sizeof(cc);
|
||||
cc.hwndOwner = hDlg;
|
||||
cc.rgbResult = in;
|
||||
cc.lpCustColors = custColors;
|
||||
cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
|
||||
if( ChooseColor( &cc ) ) init = cc.rgbResult;
|
||||
return init;
|
||||
}
|
||||
|
||||
void Colors_OnSelColor( HWND hDlg, int idx )
|
||||
{
|
||||
switch( idx )
|
||||
{
|
||||
case 0: g_rwCfg.ui.colors.npcColor = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.npcColor ); break;
|
||||
case 1: g_rwCfg.ui.colors.mobColor = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.mobColor ); break;
|
||||
case 2: g_rwCfg.ui.colors.pcColor = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.pcColor ); break;
|
||||
case 3: g_rwCfg.ui.colors.pcColorDead = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.pcColorDead ); break;
|
||||
case 4: g_rwCfg.ui.colors.pcColorParty = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.pcColorParty ); break;
|
||||
case 5: g_rwCfg.ui.colors.pcColorPartyDead = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.pcColorPartyDead ); break;
|
||||
case 6: g_rwCfg.ui.colors.pcColorWar = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.pcColorWar ); break;
|
||||
case 7: g_rwCfg.ui.colors.pcColorWarDead = Colors_MyChooseColor( hDlg, g_rwCfg.ui.colors.pcColorWarDead ); break;
|
||||
}
|
||||
RedrawWindow( hDlg, NULL, NULL, RDW_INVALIDATE );
|
||||
}
|
||||
|
||||
6
l2detect/RadarSetupDlg_Colors.h
Normal file
6
l2detect/RadarSetupDlg_Colors.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_Colors
|
||||
#define H_RadarSetupDlg_Colors
|
||||
|
||||
HWND RadarSetupDlg_Colors_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
109
l2detect/RadarSetupDlg_FolAsi.cpp
Normal file
109
l2detect/RadarSetupDlg_FolAsi.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "DlgPressKey.h"
|
||||
#include "windowUtils.h"
|
||||
#include "RadarSetupDlg_FolAsi.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_FollowAssist_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_FolAsi_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_FOLLOWASSIST),
|
||||
hWndParent, RadarSetupDlg_FollowAssist_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
void RadarSetupDlg_FollowAssist_Init( HWND hDlg );
|
||||
void RadarSetupDlg_FollowAssist_OnDestroy( HWND hDlg );
|
||||
void RadarSetupDlg_FollowAssist_OnApply( HWND hDlg );
|
||||
// =====================================
|
||||
void RadarSetupDlg_FollowAssist_UpdateDisabledWindows( HWND hDlg );
|
||||
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_FollowAssist_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: RadarSetupDlg_FollowAssist_Init( hDlg ); break;
|
||||
case WM_DESTROY: { RadarSetupDlg_FollowAssist_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: RadarSetupDlg_FollowAssist_OnApply( hDlg ); break;
|
||||
case IDC_C_FOLLOW_ENABLE:
|
||||
case IDC_C_ASSIST_ENABLE:
|
||||
RadarSetupDlg_FollowAssist_UpdateDisabledWindows( hDlg );
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RadarSetupDlg_FollowAssist_Init( HWND hDlg )
|
||||
{
|
||||
// force UserAI to reload config file
|
||||
g_game_client->ai.folAsiCfg.loadFromFile( "L2Detect_folAsi.ini" );
|
||||
// follow sets
|
||||
CheckDlgButton( hDlg, IDC_C_FOLLOW_ENABLE, g_game_client->ai.folAsiCfg.m_follow_enable );
|
||||
SetDlgItemInt( hDlg, IDC_E_FOLLOW_DISTANCE, g_game_client->ai.folAsiCfg.m_follow_dist, FALSE );
|
||||
SetDlgItemTextW( hDlg, IDC_E_NAME_FOLLOW, g_game_client->ai.folAsiCfg.m_follow_name );
|
||||
CheckDlgButton( hDlg, IDC_C_FOLLOW_ONLY_IN_PARTY, g_game_client->ai.folAsiCfg.m_follow_only_in_party );
|
||||
// assist sets
|
||||
CheckDlgButton( hDlg, IDC_C_ASSIST_ENABLE, g_game_client->ai.folAsiCfg.m_assist_enable );
|
||||
SetDlgItemTextW( hDlg, IDC_E_NAME_ASSIST, g_game_client->ai.folAsiCfg.m_assist_name );
|
||||
CheckDlgButton( hDlg, IDC_C_ASSIST_ONLY_IN_PARTY, g_game_client->ai.folAsiCfg.m_assist_only_in_party );
|
||||
CheckDlgButton( hDlg, IDC_C_DONT_ASSIST_ALLIES, g_game_client->ai.folAsiCfg.m_assist_dont_ally );
|
||||
//
|
||||
RadarSetupDlg_FollowAssist_UpdateDisabledWindows( hDlg );
|
||||
}
|
||||
|
||||
|
||||
void RadarSetupDlg_FollowAssist_OnDestroy( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
}
|
||||
|
||||
void RadarSetupDlg_FollowAssist_OnApply( HWND hDlg )
|
||||
{
|
||||
// follow sets
|
||||
g_game_client->ai.folAsiCfg.m_follow_enable = IsDlgButtonChecked( hDlg, IDC_C_FOLLOW_ENABLE );
|
||||
g_game_client->ai.folAsiCfg.m_follow_dist = (int)GetDlgItemInt( hDlg, IDC_E_FOLLOW_DISTANCE, NULL, FALSE );
|
||||
GetDlgItemTextW( hDlg, IDC_E_NAME_FOLLOW, g_game_client->ai.folAsiCfg.m_follow_name, 127 );
|
||||
g_game_client->ai.folAsiCfg.m_follow_only_in_party = IsDlgButtonChecked( hDlg, IDC_C_FOLLOW_ONLY_IN_PARTY );
|
||||
// assist sets
|
||||
g_game_client->ai.folAsiCfg.m_assist_enable = IsDlgButtonChecked( hDlg, IDC_C_ASSIST_ENABLE );
|
||||
GetDlgItemTextW( hDlg, IDC_E_NAME_ASSIST, g_game_client->ai.folAsiCfg.m_assist_name, 127 );
|
||||
g_game_client->ai.folAsiCfg.m_assist_only_in_party = IsDlgButtonChecked( hDlg, IDC_C_ASSIST_ONLY_IN_PARTY );
|
||||
g_game_client->ai.folAsiCfg.m_assist_dont_ally = IsDlgButtonChecked( hDlg, IDC_C_DONT_ASSIST_ALLIES );
|
||||
// save config to file
|
||||
g_game_client->ai.folAsiCfg.saveToFile( "L2Detect_folAsi.ini" );
|
||||
// checks
|
||||
if( !g_game_client->ai.folAsiCfg.m_follow_enable )
|
||||
g_game_client->ai.followDisable(); // zero follow objectID
|
||||
if( !g_game_client->ai.folAsiCfg.m_assist_enable )
|
||||
g_game_client->ai.assistDisable(); // zero assist objectID
|
||||
}
|
||||
|
||||
void RadarSetupDlg_FollowAssist_UpdateDisabledWindows( HWND hDlg )
|
||||
{
|
||||
BOOL b = FALSE;
|
||||
if( IsDlgButtonChecked( hDlg, IDC_C_FOLLOW_ENABLE ) ) b = TRUE;
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_NAME_FOLLOW ), b );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_FOLLOW_ONLY_IN_PARTY ), b );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_FOLLOW_DISTANCE ), b );
|
||||
b = FALSE;
|
||||
if( IsDlgButtonChecked( hDlg, IDC_C_ASSIST_ENABLE ) ) b = TRUE;
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_NAME_ASSIST ), b );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_ASSIST_ONLY_IN_PARTY ), b );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_C_DONT_ASSIST_ALLIES ), b );
|
||||
}
|
||||
6
l2detect/RadarSetupDlg_FolAsi.h
Normal file
6
l2detect/RadarSetupDlg_FolAsi.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_FolAsi
|
||||
#define H_RadarSetupDlg_FolAsi
|
||||
|
||||
HWND RadarSetupDlg_FolAsi_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
61
l2detect/RadarSetupDlg_InvisGM.cpp
Normal file
61
l2detect/RadarSetupDlg_InvisGM.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "ConfigIni.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern CConfig g_cfg;
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_InvisGM_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_InvisGM_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_INVISGM),
|
||||
hWndParent, RadarSetupDlg_InvisGM_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
void RadarSetupDlg_InvisGM_Init( HWND hDlg );
|
||||
void RadarSetupDlg_InvisGM_OnDestroy( HWND hDlg );
|
||||
void RadarSetupDlg_InvisGM_OnApply( HWND hDlg );
|
||||
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_InvisGM_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: RadarSetupDlg_InvisGM_Init( hDlg ); break;
|
||||
case WM_DESTROY: { RadarSetupDlg_InvisGM_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: RadarSetupDlg_InvisGM_OnApply( hDlg ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RadarSetupDlg_InvisGM_Init( HWND hDlg )
|
||||
{
|
||||
CheckDlgButton( hDlg, IDC_C_INVIS_GM_ENABLE, g_cfg.InvisGMTrackEnable );
|
||||
SetDlgItemInt( hDlg, IDC_E_INVIS_GM_SPEED, g_cfg.InvisGMSpeed, TRUE );
|
||||
}
|
||||
|
||||
|
||||
void RadarSetupDlg_InvisGM_OnDestroy( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
}
|
||||
|
||||
void RadarSetupDlg_InvisGM_OnApply( HWND hDlg )
|
||||
{
|
||||
g_cfg.InvisGMTrackEnable = IsDlgButtonChecked( hDlg, IDC_C_INVIS_GM_ENABLE );
|
||||
g_cfg.InvisGMSpeed = GetDlgItemInt( hDlg, IDC_E_INVIS_GM_SPEED, NULL, TRUE );
|
||||
g_cfg.SaveConfig();
|
||||
}
|
||||
|
||||
6
l2detect/RadarSetupDlg_InvisGM.h
Normal file
6
l2detect/RadarSetupDlg_InvisGM.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_InvisGM
|
||||
#define H_RadarSetupDlg_InvisGM
|
||||
|
||||
HWND RadarSetupDlg_InvisGM_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
63
l2detect/RadarSetupDlg_LT.cpp
Normal file
63
l2detect/RadarSetupDlg_LT.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client;
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_LockTarget_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_LockTarget_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_LOCKTARGET),
|
||||
hWndParent, RadarSetupDlg_LockTarget_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
void RadarSetupDlg_LockTarget_Init( HWND hDlg );
|
||||
void RadarSetupDlg_LockTarget_OnDestroy( HWND hDlg );
|
||||
void RadarSetupDlg_LockTarget_OnApply( HWND hDlg );
|
||||
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_LockTarget_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: RadarSetupDlg_LockTarget_Init( hDlg ); break;
|
||||
case WM_DESTROY: { RadarSetupDlg_LockTarget_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: RadarSetupDlg_LockTarget_OnApply( hDlg ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RadarSetupDlg_LockTarget_Init( HWND hDlg )
|
||||
{
|
||||
int e = g_game_client->ai.lockTargetMgr.isEnabled() ? 1 : 0;
|
||||
CheckDlgButton( hDlg, IDC_C_LT_ENABLED, e );
|
||||
}
|
||||
|
||||
|
||||
void RadarSetupDlg_LockTarget_OnDestroy( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
}
|
||||
|
||||
void RadarSetupDlg_LockTarget_OnApply( HWND hDlg )
|
||||
{
|
||||
int e = IsDlgButtonChecked( hDlg, IDC_C_LT_ENABLED );
|
||||
if( e == 0 )
|
||||
g_game_client->ai.lockTargetMgr.setEnable( false );
|
||||
else
|
||||
g_game_client->ai.lockTargetMgr.setEnable( true );
|
||||
}
|
||||
|
||||
6
l2detect/RadarSetupDlg_LT.h
Normal file
6
l2detect/RadarSetupDlg_LT.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_LockTarget
|
||||
#define H_RadarSetupDlg_LockTarget
|
||||
|
||||
HWND RadarSetupDlg_LockTarget_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
175
l2detect/RadarSetupDlg_OffpartyBDSWS.cpp
Normal file
175
l2detect/RadarSetupDlg_OffpartyBDSWS.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "UserAI_OffpartyBDSWS.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
INT_PTR CALLBACK OFFBDSWS_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_OFFBDSWS_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_OFFPARTYBDSWS),
|
||||
hWndParent, OFFBDSWS_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
UserAI_OffpartyBDSWS *rsobdsws;
|
||||
|
||||
void OFFBDSWS_Init( HWND hDlg );
|
||||
void OFFBDSWS_OnDestroy( HWND hDlg );
|
||||
void OFFBDSWS_OnApply( HWND hDlg );
|
||||
void OFFBDSWS_OnSave( HWND hDlg );
|
||||
void OFFBDSWS_OnEnable( HWND hDlg );
|
||||
void OFFBDSWS_On_C_InvBD( HWND hDlg );
|
||||
void OFFBDSWS_On_C_InvSWS( HWND hDlg );
|
||||
|
||||
|
||||
INT_PTR CALLBACK OFFBDSWS_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: OFFBDSWS_Init( hDlg ); break;
|
||||
case WM_DESTROY: { OFFBDSWS_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: OFFBDSWS_OnApply( hDlg ); break;
|
||||
case IDC_SAVE: OFFBDSWS_OnSave( hDlg ); break;
|
||||
case IDC_ENABLE: OFFBDSWS_OnEnable( hDlg ); break;
|
||||
case IDC_C_INVBD: OFFBDSWS_On_C_InvBD( hDlg ); break;
|
||||
case IDC_C_INVSWS: OFFBDSWS_On_C_InvSWS( hDlg ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void OFFBDSWS_Init( HWND hDlg )
|
||||
{
|
||||
//log_error( LOG_OK, "init\n" );
|
||||
rsobdsws = new UserAI_OffpartyBDSWS();
|
||||
rsobdsws->readFromFile( "L2Detect_offp_BDSWS.ini" );
|
||||
//
|
||||
HWND h;
|
||||
h = GetDlgItem( hDlg, IDC_ENABLE );
|
||||
if( rsobdsws->allEnabled ) SetWindowText( h, TEXT("Disable") );
|
||||
else SetWindowText( h, TEXT("Enable") );
|
||||
|
||||
SetDlgItemText( hDlg, IDC_E_BDNAME, rsobdsws->nameBD );
|
||||
SetDlgItemText( hDlg, IDC_E_SWSNAME, rsobdsws->nameSWS );
|
||||
|
||||
SetDlgItemInt( hDlg, IDC_E_INV_BD_SEC, rsobdsws->inv_bd_secs, TRUE );
|
||||
SetDlgItemInt( hDlg, IDC_E_INV_SWS_SEC, rsobdsws->inv_sws_secs, TRUE );
|
||||
|
||||
SetDlgItemInt( hDlg, IDC_E_DISMISS_BD_SEC, rsobdsws->dismiss_bd_secs, TRUE );
|
||||
SetDlgItemInt( hDlg, IDC_E_DISMISS_SWS_SEC, rsobdsws->dismiss_sws_secs, TRUE );
|
||||
|
||||
if( rsobdsws->inv_bd_enable ) CheckDlgButton( hDlg, IDC_C_INVBD, TRUE );
|
||||
else CheckDlgButton( hDlg, IDC_C_INVBD, FALSE );
|
||||
OFFBDSWS_On_C_InvBD( hDlg );
|
||||
|
||||
if( rsobdsws->inv_sws_enable ) CheckDlgButton( hDlg, IDC_C_INVSWS, TRUE );
|
||||
else CheckDlgButton( hDlg, IDC_C_INVSWS, FALSE );
|
||||
OFFBDSWS_On_C_InvSWS( hDlg );
|
||||
}
|
||||
|
||||
|
||||
void OFFBDSWS_OnDestroy( HWND hDlg )
|
||||
{
|
||||
hDlg;
|
||||
//log_error( LOG_OK, "close\n" );
|
||||
delete rsobdsws;
|
||||
rsobdsws = NULL;
|
||||
}
|
||||
|
||||
void OFFBDSWS_OnApply( HWND hDlg )
|
||||
{
|
||||
//log_error( LOG_OK, "OFFBDSWS_OnApply\n" );
|
||||
int c = IsDlgButtonChecked( hDlg, IDC_C_INVBD );
|
||||
if( c ) rsobdsws->inv_bd_enable = 1;
|
||||
else rsobdsws->inv_bd_enable = 0;
|
||||
c = IsDlgButtonChecked( hDlg, IDC_C_INVSWS );
|
||||
if( c ) rsobdsws->inv_sws_enable = 1;
|
||||
else rsobdsws->inv_sws_enable = 0;
|
||||
//
|
||||
GetDlgItemTextW( hDlg, IDC_E_BDNAME, rsobdsws->nameBD, 63 );
|
||||
GetDlgItemTextW( hDlg, IDC_E_SWSNAME, rsobdsws->nameSWS, 63 );
|
||||
//
|
||||
rsobdsws->inv_bd_secs = GetDlgItemInt( hDlg, IDC_E_INV_BD_SEC, NULL, TRUE );
|
||||
rsobdsws->inv_sws_secs = GetDlgItemInt( hDlg, IDC_E_INV_SWS_SEC, NULL, TRUE );
|
||||
//
|
||||
rsobdsws->dismiss_bd_secs = GetDlgItemInt( hDlg, IDC_E_DISMISS_BD_SEC, NULL, TRUE );
|
||||
rsobdsws->dismiss_sws_secs = GetDlgItemInt( hDlg, IDC_E_DISMISS_SWS_SEC, NULL, TRUE );
|
||||
//
|
||||
// apply setup immediately
|
||||
g_game_client->ai.setOffpartyBDSWS_Config( rsobdsws );
|
||||
//rsobdsws->saveToFile( "L2Detect_offp_BDSWS.ini" );
|
||||
}
|
||||
|
||||
void OFFBDSWS_OnSave( HWND hDlg )
|
||||
{
|
||||
hDlg;
|
||||
rsobdsws->saveToFile( "L2Detect_offp_BDSWS.ini" );
|
||||
}
|
||||
|
||||
// apply enable state immediately
|
||||
void OFFBDSWS_OnEnable( HWND hDlg )
|
||||
{
|
||||
HWND h = GetDlgItem( hDlg, IDC_ENABLE );
|
||||
if( rsobdsws->allEnabled == 1 )
|
||||
{
|
||||
rsobdsws->allEnabled = 0;
|
||||
rsobdsws->saveToFile( "L2Detect_offp_BDSWS.ini" );
|
||||
g_game_client->ai.setOffpartyBDSWS_Enable( false );
|
||||
SetWindowText( h, TEXT("Enable") );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
rsobdsws->allEnabled = 1;
|
||||
rsobdsws->saveToFile( "L2Detect_offp_BDSWS.ini" );
|
||||
g_game_client->ai.setOffpartyBDSWS_Enable( true );
|
||||
SetWindowText( h, TEXT("Disable") );
|
||||
}
|
||||
}
|
||||
|
||||
void OFFBDSWS_On_C_InvBD( HWND hDlg )
|
||||
{
|
||||
int c = IsDlgButtonChecked( hDlg, IDC_C_INVBD );
|
||||
if( c )
|
||||
{
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_BDNAME ), TRUE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_INV_BD_SEC ), TRUE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_DISMISS_BD_SEC ), TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_BDNAME ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_INV_BD_SEC ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_DISMISS_BD_SEC ), FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
void OFFBDSWS_On_C_InvSWS( HWND hDlg )
|
||||
{
|
||||
int c = IsDlgButtonChecked( hDlg, IDC_C_INVSWS );
|
||||
if( c )
|
||||
{
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_SWSNAME ), TRUE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_INV_SWS_SEC ), TRUE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_DISMISS_SWS_SEC ), TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_SWSNAME ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_INV_SWS_SEC ), FALSE );
|
||||
EnableWindow( GetDlgItem( hDlg, IDC_E_DISMISS_SWS_SEC ), FALSE );
|
||||
}
|
||||
}
|
||||
6
l2detect/RadarSetupDlg_OffpartyBDSWS.h
Normal file
6
l2detect/RadarSetupDlg_OffpartyBDSWS.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_OffpartyBDSWS
|
||||
#define H_RadarSetupDlg_OffpartyBDSWS
|
||||
|
||||
HWND RadarSetupDlg_OFFBDSWS_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
283
l2detect/RadarSetupDlg_QuickTarget.cpp
Normal file
283
l2detect/RadarSetupDlg_QuickTarget.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "DlgPressKey.h"
|
||||
#include "windowUtils.h"
|
||||
#include "RadarSetupDlg_QuickTarget_distPri.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
INT_PTR CALLBACK QuickTarget_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_QuickTarget_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_QUICKTARGET),
|
||||
hWndParent, QuickTarget_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
void QuickTarget_Init( HWND hDlg );
|
||||
void QuickTarget_OnDestroy( HWND hDlg );
|
||||
void QuickTarget_OnApply( HWND hDlg );
|
||||
void QuickTarget_OnNotify( HWND hDlg, LPARAM lParam );
|
||||
|
||||
void QuickTarget_OnLvBeginLabelEdit( HWND hDlg, LPNMHDR pnmh );
|
||||
void QuickTarget_OnLvEndLabelEdit( HWND hDlg, LPNMHDR pnmh );
|
||||
void QuickTarget_OnLvDoubleClick( HWND hDlg, LPNMHDR pnmh );
|
||||
void QuickTarget_OnLvColumnClick( HWND hDlg, LPNMHDR pnmh );
|
||||
|
||||
void QuickTarget_FillClassList( HWND hDlg );
|
||||
void QuickTarget_DisplayKey( HWND hDlg, int vkey );
|
||||
|
||||
void QuickTarget_SetKey( HWND hDlg );
|
||||
|
||||
|
||||
INT_PTR CALLBACK QuickTarget_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: QuickTarget_Init( hDlg ); break;
|
||||
case WM_DESTROY: { QuickTarget_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_NOTIFY: QuickTarget_OnNotify( hDlg, lParam ); break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: QuickTarget_OnApply( hDlg ); break;
|
||||
case IDC_B_SET_TARGET_KEY: QuickTarget_SetKey( hDlg ); break;
|
||||
case IDC_B_DISTANCE_SETUP: RadarSetupDlg_QuickTarget_SetupDistancePriorities( hDlg ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void QuickTarget_Init( HWND hDlg )
|
||||
{
|
||||
// force UserAI to reload config file
|
||||
g_game_client->ai.cfgQuickTarg.loadFromFile( "L2Detect_quickTarg.ini" );
|
||||
// init class pri list view
|
||||
HWND hWndClassList = GetDlgItem( hDlg, IDC_CLASSLIST );
|
||||
WULV_SetExtStyle( hWndClassList, true, true );
|
||||
WULV_InsertColumn( hWndClassList, TEXT("class"), 120, 0 );
|
||||
WULV_InsertColumn( hWndClassList, TEXT("pri"), 35, 1 );
|
||||
// init tab
|
||||
HWND hwndTab = GetDlgItem( hDlg, IDC_TAB1 );
|
||||
WUTab_InsertItem( hwndTab, TEXT("PC list"), 0 );
|
||||
WUTab_InsertItem( hwndTab, TEXT("Enemy list"), 1 );
|
||||
//
|
||||
QuickTarget_FillClassList( hDlg );
|
||||
QuickTarget_DisplayKey( hDlg, g_game_client->ai.cfgQuickTarg.getKey() );
|
||||
SetDlgItemInt( hDlg, IDC_E_MAXDIST, g_game_client->ai.cfgQuickTarg.getMaxDist(), FALSE );
|
||||
CheckDlgButton( hDlg, IDC_C_SHOUT_TARGET_IN_PARTY_CHAT, g_game_client->ai.cfgQuickTarg.getAnnounceTargetInPartyChat() );
|
||||
//CheckDlgButton( hDlg, IDC_C_DONT_TARGET_DEAD, g_game_client->ai.cfgQuickTarg.opt_dontTargetDead() );
|
||||
//CheckDlgButton( hDlg, IDC_C_DONT_TARGET_PARTY, g_game_client->ai.cfgQuickTarg.opt_dontTargetParty() );
|
||||
//CheckDlgButton( hDlg, IDC_C_DONT_TARGET_CLAN, g_game_client->ai.cfgQuickTarg.opt_dontTargetClan() );
|
||||
//CheckDlgButton( hDlg, IDC_C_DONT_TARGET_ALLY, g_game_client->ai.cfgQuickTarg.opt_dontTargetAlly() );
|
||||
//CheckDlgButton( hDlg, IDC_C_TARGET_ONLY_CW, g_game_client->ai.cfgQuickTarg.opt_targetOnlyCW() );
|
||||
//CheckDlgButton( hDlg, IDC_C_TARGET_ALSO_PK, g_game_client->ai.cfgQuickTarg.opt_allowTargetPK() );
|
||||
//CheckDlgButton( hDlg, IDC_C_TARGET_ALSO_FLAGGED, g_game_client->ai.cfgQuickTarg.opt_allowTargetFlagged() );
|
||||
}
|
||||
|
||||
|
||||
void QuickTarget_OnDestroy( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
}
|
||||
|
||||
void QuickTarget_OnApply( HWND hDlg )
|
||||
{
|
||||
HWND hWndClassList = GetDlgItem( hDlg, IDC_CLASSLIST );
|
||||
// apply class priorities
|
||||
ClassPriorities *pri = g_game_client->ai.cfgQuickTarg.getClassPriorities();
|
||||
wchar_t spri[32];
|
||||
int iItem = -1;
|
||||
iItem = ListView_GetNextItem( hWndClassList, iItem, LVNI_ALL );
|
||||
while( iItem != -1 )
|
||||
{
|
||||
int classId = WULV_GetItemLPARAM( hWndClassList, iItem );
|
||||
*((int *)(&spri[0])) = 0;
|
||||
WULV_GetItemText( hWndClassList, iItem, 1, spri, 31 );
|
||||
int ipri = 0;
|
||||
swscanf( spri, L"%d", &ipri );
|
||||
pri->setPriForClass( classId, ipri );
|
||||
iItem = ListView_GetNextItem( hWndClassList, iItem, LVNI_ALL );
|
||||
}
|
||||
// apply hotkey
|
||||
int hotkey_vcode = 0;
|
||||
GetDlgItemText( hDlg, IDC_E_KEY, spri, 31 );
|
||||
swscanf( spri, L"%d", &hotkey_vcode );
|
||||
g_game_client->ai.cfgQuickTarg.setKey( hotkey_vcode );
|
||||
// apply max dist
|
||||
g_game_client->ai.cfgQuickTarg.setMaxDist( (int)GetDlgItemInt( hDlg, IDC_E_MAXDIST, NULL, FALSE ) );
|
||||
// apply shout in party
|
||||
g_game_client->ai.cfgQuickTarg.setAnnounceTargetInPartyChat( (int)GetDlgItemInt( hDlg, IDC_C_SHOUT_TARGET_IN_PARTY_CHAT, NULL, FALSE ) );
|
||||
// apply "don't" checks
|
||||
/*g_game_client->ai.cfgQuickTarg.setTargetParams(
|
||||
IsDlgButtonChecked( hDlg, IDC_C_DONT_TARGET_DEAD ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_DONT_TARGET_PARTY ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_DONT_TARGET_CLAN ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_DONT_TARGET_ALLY ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_TARGET_ONLY_CW ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_TARGET_ALSO_PK ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_TARGET_ALSO_FLAGGED ),
|
||||
IsDlgButtonChecked( hDlg, IDC_C_SHOUT_TARGET_IN_PARTY_CHAT )
|
||||
);*/
|
||||
// save config to file
|
||||
g_game_client->ai.cfgQuickTarg.saveToFile( "L2Detect_quickTarg.ini" );
|
||||
}
|
||||
|
||||
void QuickTarget_FillClassList( HWND hDlg )
|
||||
{
|
||||
HWND hWndClassList = GetDlgItem( hDlg, IDC_CLASSLIST );
|
||||
SendMessage( hWndClassList, LVM_DELETEALLITEMS, 0, 0 ); // clear LV
|
||||
ClassPriorities *pri = g_game_client->ai.cfgQuickTarg.getClassPriorities();
|
||||
int i;
|
||||
for( i=0; i<L2MaxClasses; i++ )
|
||||
{
|
||||
const char *acn = L2Data_getClass( i );
|
||||
if( acn )
|
||||
{
|
||||
wchar_t wcn[128]; wcn[0] = 0;
|
||||
MultiByteToWideChar( CP_ACP, 0, acn, -1, wcn, 127 );
|
||||
int ipri = pri->getPriForClass( i );
|
||||
if( ipri >= 0 )
|
||||
{
|
||||
int added_item_index = WULV_InsertItem( hWndClassList, wcn, 999, (LPARAM)i );
|
||||
swprintf( wcn, 127, L"%d", ipri );
|
||||
WULV_SetItem( hWndClassList, wcn, added_item_index, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuickTarget_DisplayKey( HWND hDlg, int vkey )
|
||||
{
|
||||
wchar_t sz[64];
|
||||
wchar_t szz[32];
|
||||
swprintf( sz, 63, L"%d ", vkey ); // vkey code
|
||||
if( ( (vkey>='A') && (vkey<='Z') ) || ( (vkey>='0') && (vkey<='9') ) )
|
||||
{
|
||||
swprintf( szz, 31, _T("'%c'"), vkey );
|
||||
wcscat( sz, szz );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( vkey )
|
||||
{
|
||||
case VK_ESCAPE: wcscat( sz, L"Esc" ); break;
|
||||
case VK_OEM_3: wcscat( sz, L"~" ); break;
|
||||
case VK_SNAPSHOT: wcscat( sz, L"PrtScr" ); break;
|
||||
case VK_SCROLL: wcscat( sz, L"ScrollLock" ); break;
|
||||
case VK_PAUSE: wcscat( sz, L"Pause" ); break;
|
||||
case VK_RETURN: wcscat( sz, L"Enter" ); break;
|
||||
case VK_SPACE: wcscat( sz, L"Spacebar" ); break;
|
||||
// TODO: other key codes... <20><><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
}
|
||||
SetDlgItemTextW( hDlg, IDC_E_KEY, sz );
|
||||
}
|
||||
|
||||
void QuickTarget_SetKey( HWND hDlg )
|
||||
{
|
||||
int vkey = DlgPressKey_InputPressKey( hDlg );
|
||||
if( vkey <= 0 ) return;
|
||||
QuickTarget_DisplayKey( hDlg, vkey );
|
||||
}
|
||||
|
||||
void QuickTarget_OnNotify( HWND hDlg, LPARAM lParam )
|
||||
{
|
||||
LPNMHDR pnmh = (LPNMHDR)lParam;
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_CLASSLIST );
|
||||
if( hwndLV == pnmh->hwndFrom ) // if notification from ClassList ListView
|
||||
{
|
||||
switch( pnmh->code )
|
||||
{
|
||||
case LVN_BEGINLABELEDIT: QuickTarget_OnLvBeginLabelEdit( hDlg, pnmh ); break;
|
||||
case LVN_ENDLABELEDIT: QuickTarget_OnLvEndLabelEdit( hDlg, pnmh ); break;
|
||||
case NM_DBLCLK: QuickTarget_OnLvDoubleClick( hDlg, pnmh ); break;
|
||||
case LVN_COLUMNCLICK: QuickTarget_OnLvColumnClick( hDlg, pnmh ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QuickTarget_OnLvBeginLabelEdit( HWND hDlg, LPNMHDR pnmh )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_CLASSLIST );
|
||||
HWND hwndEdit = (HWND)SendMessage( hwndLV, LVM_GETEDITCONTROL, 0, 0 );
|
||||
if( !hwndEdit ) return;
|
||||
NMLVDISPINFO *pnmlvdispinfo = (NMLVDISPINFO *)pnmh;
|
||||
int iItem = pnmlvdispinfo->item.iItem;
|
||||
wchar_t pri_text[128] = {0};
|
||||
WULV_GetItemText( hwndLV, iItem, 1, pri_text, 127 );
|
||||
DWORD dwOldEditStyle = GetWindowLong( hwndEdit, GWL_STYLE );
|
||||
SetWindowLong( hwndEdit, GWL_STYLE, dwOldEditStyle | ES_NUMBER ); // allow only number input
|
||||
SetWindowText( hwndEdit, pri_text );
|
||||
}
|
||||
|
||||
void QuickTarget_OnLvEndLabelEdit( HWND hDlg, LPNMHDR pnmh )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_CLASSLIST );
|
||||
NMLVDISPINFO *pnmlvdispinfo = (NMLVDISPINFO *)pnmh;
|
||||
int iItem = pnmlvdispinfo->item.iItem;
|
||||
wchar_t *newText = pnmlvdispinfo->item.pszText;
|
||||
if( !newText ) return;
|
||||
int new_pri = 0;
|
||||
swscanf( newText, L"%d", &new_pri );
|
||||
wchar_t ttext[32];
|
||||
swprintf( ttext, 31, L"%d", new_pri );
|
||||
WULV_SetItem( hwndLV, ttext, iItem, 1 );
|
||||
}
|
||||
|
||||
void QuickTarget_OnLvDoubleClick( HWND hDlg, LPNMHDR pnmh )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
NMITEMACTIVATE *p = (NMITEMACTIVATE *)pnmh;
|
||||
ListView_EditLabel( pnmh->hwndFrom, p->iItem );
|
||||
}
|
||||
|
||||
int CALLBACK QuickTarget_LVCompareFunc1( LPARAM iItem1, LPARAM iItem2, LPARAM lpHWND );
|
||||
int CALLBACK QuickTarget_LVCompareFunc2( LPARAM iItem1, LPARAM iItem2, LPARAM lpHWND );
|
||||
|
||||
void QuickTarget_OnLvColumnClick( HWND hDlg, LPNMHDR pnmh )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
int iCol = ((NMLISTVIEW *)pnmh)->iSubItem;
|
||||
switch( iCol )
|
||||
{
|
||||
case 0: ListView_SortItemsEx( pnmh->hwndFrom, QuickTarget_LVCompareFunc1, (LPARAM)pnmh->hwndFrom ); break;
|
||||
case 1: ListView_SortItemsEx( pnmh->hwndFrom, QuickTarget_LVCompareFunc2, (LPARAM)pnmh->hwndFrom ); break;
|
||||
}
|
||||
}
|
||||
|
||||
// sort by class name A -> Z
|
||||
int CALLBACK QuickTarget_LVCompareFunc1( LPARAM iItem1, LPARAM iItem2, LPARAM lpHWND )
|
||||
{
|
||||
HWND hwndLV = (HWND)lpHWND;
|
||||
TCHAR text1[256], text2[256];
|
||||
text1[0] = text2[0] = 0;
|
||||
WULV_GetItemText( hwndLV, iItem1, 0, text1, 255 );
|
||||
WULV_GetItemText( hwndLV, iItem2, 0, text2, 255 );
|
||||
return _tcscmp( text1, text2 );
|
||||
}
|
||||
|
||||
// sort by priority 999 -> 0
|
||||
int CALLBACK QuickTarget_LVCompareFunc2( LPARAM iItem1, LPARAM iItem2, LPARAM lpHWND )
|
||||
{
|
||||
HWND hwndLV = (HWND)lpHWND;
|
||||
TCHAR text1[256], text2[256];
|
||||
text1[0] = text2[0] = 0;
|
||||
WULV_GetItemText( hwndLV, iItem1, 1, text1, 255 );
|
||||
WULV_GetItemText( hwndLV, iItem2, 1, text2, 255 );
|
||||
int pri1 = 0, pri2 = 0;
|
||||
_stscanf( text1, _T("%d"), &pri1 );
|
||||
_stscanf( text2, _T("%d"), &pri2 );
|
||||
if( pri1 == pri2 ) return 0;
|
||||
if( pri1 > pri2 ) return -1;
|
||||
return 1;
|
||||
}
|
||||
6
l2detect/RadarSetupDlg_QuickTarget.h
Normal file
6
l2detect/RadarSetupDlg_QuickTarget.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_QuickTarget
|
||||
#define H_RadarSetupDlg_QuickTarget
|
||||
|
||||
HWND RadarSetupDlg_QuickTarget_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
199
l2detect/RadarSetupDlg_QuickTarget_distPri.cpp
Normal file
199
l2detect/RadarSetupDlg_QuickTarget_distPri.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "Resource.h"
|
||||
#include "windowUtils.h"
|
||||
#include "GameClient.h"
|
||||
|
||||
extern class GameClient *g_game_client;
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
|
||||
struct rsdqtsdp_RANGE_INFO
|
||||
{
|
||||
int min;
|
||||
int max;
|
||||
int pri;
|
||||
};
|
||||
|
||||
INT_PTR CALLBACK rsdqtsdp_EditRange_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
bool rsdqtsdp_launch_edit_dlg( HWND hDlg, rsdqtsdp_RANGE_INFO *st )
|
||||
{
|
||||
INT_PTR ret = DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_DISTPRI_EDITPRI), hDlg,
|
||||
rsdqtsdp_EditRange_DlgProc, (LPARAM)st );
|
||||
if( ret == IDOK ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void rsdqtsdp_add_range( HWND hDlg )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
|
||||
int cur_sel = WULV_GetCurSelItem( hwndLV );
|
||||
if( cur_sel == -1 ) cur_sel = 999;
|
||||
rsdqtsdp_RANGE_INFO inf = { 0, 0, 0 };
|
||||
if( rsdqtsdp_launch_edit_dlg( hDlg, &inf ) )
|
||||
{
|
||||
TCHAR txt[32] = {0};
|
||||
swprintf( txt, 31, L"%d", inf.min );
|
||||
int added_idx = WULV_InsertItem( hwndLV, txt, cur_sel );
|
||||
if( added_idx >= 0 )
|
||||
{
|
||||
swprintf( txt, 31, L"%d", inf.max );
|
||||
WULV_SetItem( hwndLV, txt, added_idx, 1 );
|
||||
swprintf( txt, 31, L"%d", inf.pri );
|
||||
WULV_SetItem( hwndLV, txt, added_idx, 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rsdqtsdp_edit_range( HWND hDlg )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
|
||||
int cur_sel = WULV_GetCurSelItem( hwndLV );
|
||||
if( cur_sel == -1 ) return;
|
||||
rsdqtsdp_RANGE_INFO inf;
|
||||
TCHAR txt[32] = {0};
|
||||
WULV_GetItemText( hwndLV, cur_sel, 0, txt, 31 );
|
||||
swscanf( txt, L"%d", &(inf.min) );
|
||||
WULV_GetItemText( hwndLV, cur_sel, 1, txt, 31 );
|
||||
swscanf( txt, L"%d", &(inf.max) );
|
||||
WULV_GetItemText( hwndLV, cur_sel, 2, txt, 31 );
|
||||
swscanf( txt, L"%d", &(inf.pri) );
|
||||
if( rsdqtsdp_launch_edit_dlg( hDlg, &inf ) )
|
||||
{
|
||||
swprintf( txt, 31, L"%d", inf.min );
|
||||
WULV_SetItem( hwndLV, txt, cur_sel, 0 );
|
||||
swprintf( txt, 31, L"%d", inf.max );
|
||||
WULV_SetItem( hwndLV, txt, cur_sel, 1 );
|
||||
swprintf( txt, 31, L"%d", inf.pri );
|
||||
WULV_SetItem( hwndLV, txt, cur_sel, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
void rsdqtsdp_del_range( HWND hDlg )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
|
||||
int cur_sel = WULV_GetCurSelItem( hwndLV );
|
||||
if( cur_sel == -1 ) return;
|
||||
ListView_DeleteItem( hwndLV, cur_sel );
|
||||
}
|
||||
|
||||
void rsdqtsdp_fill_lv( HWND hDlg )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
|
||||
SendMessage( hwndLV, LVM_DELETEALLITEMS, 0, 0 );
|
||||
int i;
|
||||
DistancePriorities *dpri = g_game_client->ai.cfgQuickTarg.getDistancePriorities();
|
||||
for( i=0; i<dpri->MAXN; i++ )
|
||||
{
|
||||
int min=-1, max=-1, pri=0;
|
||||
dpri->getRangeInfo( i, &min, &max, &pri );
|
||||
if( min>=0 && max>=0 )
|
||||
{
|
||||
TCHAR txt[32];
|
||||
swprintf( txt, 31, L"%d", min );
|
||||
int added_item = WULV_InsertItem( hwndLV, txt, 999 );
|
||||
if( added_item >= 0 )
|
||||
{
|
||||
swprintf( txt, 31, L"%d", max );
|
||||
WULV_SetItem( hwndLV, txt, added_item, 1 );
|
||||
swprintf( txt, 31, L"%d", pri );
|
||||
WULV_SetItem( hwndLV, txt, added_item, 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK RadarSetupDlg_QuickTarget_SetupDistancePriorities_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
|
||||
WULV_SetExtStyle( hwndLV, true, true );
|
||||
WULV_InsertColumn( hwndLV, TEXT("[min"), 55, 0 );
|
||||
WULV_InsertColumn( hwndLV, TEXT("max)"), 55, 1 );
|
||||
WULV_InsertColumn( hwndLV, TEXT("pri_mod"), 60, 2 );
|
||||
rsdqtsdp_fill_lv( hDlg );
|
||||
lParam = 0; // fix warn unref. param
|
||||
} break;
|
||||
case WM_COMMAND:
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
case IDC_B_ADD: rsdqtsdp_add_range( hDlg ); break;
|
||||
case IDC_B_EDIT: rsdqtsdp_edit_range( hDlg ); break;
|
||||
case IDC_B_DEL: rsdqtsdp_del_range( hDlg ); break;
|
||||
case IDOK:
|
||||
{
|
||||
DistancePriorities *dpri = g_game_client->ai.cfgQuickTarg.getDistancePriorities();
|
||||
dpri->removeAll();
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
|
||||
TCHAR txt[32] = {0};
|
||||
int min, max, pri;
|
||||
int iItem = -1;
|
||||
iItem = ListView_GetNextItem( hwndLV, iItem, LVNI_ALL );
|
||||
while( iItem >= 0 )
|
||||
{
|
||||
WULV_GetItemText( hwndLV, iItem, 0, txt, 31 );
|
||||
swscanf( txt, L"%d", &min );
|
||||
WULV_GetItemText( hwndLV, iItem, 1, txt, 31 );
|
||||
swscanf( txt, L"%d", &max );
|
||||
WULV_GetItemText( hwndLV, iItem, 2, txt, 31 );
|
||||
swscanf( txt, L"%d", &pri );
|
||||
if( dpri->addRangePri( min, max, pri ) < 0 )
|
||||
log_error( LOG_ERROR, "RadarSetupDlg_QuickTarget_SetupDistancePriorities_DlgProc "
|
||||
"on OK: failed to add dist pri range [%d-%d,%d]\n", min, max, pri );
|
||||
iItem = ListView_GetNextItem( hwndLV, iItem, LVNI_ALL );
|
||||
}
|
||||
EndDialog( hDlg, IDOK );
|
||||
} break;
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE: EndDialog( hDlg, IDCANCEL ); break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RadarSetupDlg_QuickTarget_SetupDistancePriorities( HWND hWndParent )
|
||||
{
|
||||
DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_DISTPRI), hWndParent,
|
||||
RadarSetupDlg_QuickTarget_SetupDistancePriorities_DlgProc, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
INT_PTR CALLBACK rsdqtsdp_EditRange_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
SetWindowLongPtr( hDlg, GWLP_USERDATA, lParam );
|
||||
rsdqtsdp_RANGE_INFO *st = (rsdqtsdp_RANGE_INFO *)lParam;
|
||||
SetDlgItemInt( hDlg, IDC_E_MIN, st->min, TRUE );
|
||||
SetDlgItemInt( hDlg, IDC_E_MAX, st->max, TRUE );
|
||||
SetDlgItemInt( hDlg, IDC_E_PRI, st->pri, TRUE );
|
||||
} break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
rsdqtsdp_RANGE_INFO *st = (rsdqtsdp_RANGE_INFO *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||||
st->min = (int)GetDlgItemInt( hDlg, IDC_E_MIN, NULL, TRUE );
|
||||
st->max = (int)GetDlgItemInt( hDlg, IDC_E_MAX, NULL, TRUE );
|
||||
st->pri = (int)GetDlgItemInt( hDlg, IDC_E_PRI, NULL, TRUE );
|
||||
EndDialog( hDlg, IDOK );
|
||||
} break;
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
} break;
|
||||
case WM_CLOSE: EndDialog( hDlg, IDCANCEL ); break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
3
l2detect/RadarSetupDlg_QuickTarget_distPri.h
Normal file
3
l2detect/RadarSetupDlg_QuickTarget_distPri.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void RadarSetupDlg_QuickTarget_SetupDistancePriorities( HWND hWndParent );
|
||||
408
l2detect/RadarSetupDlg_SelfHeal.cpp
Normal file
408
l2detect/RadarSetupDlg_SelfHeal.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "HealItemsTable.h"
|
||||
#include "GameClient.h"
|
||||
#include "Dlg_FindInDB.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
INT_PTR CALLBACK SelfHealSetup_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_SelfHeal_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_SELFHEAL),
|
||||
hWndParent, SelfHealSetup_DlgProc, 0 );
|
||||
}
|
||||
|
||||
HealItemsTable *rssh_hit;
|
||||
int rssh_cur_sel;
|
||||
//HWND SelfHealSetup_saveHWND;
|
||||
|
||||
void SelfHealSetup_Init( HWND hDlg );
|
||||
void SelfHealSetup_OnDestroy( HWND hDlg );
|
||||
void SelfHealSetup_OnCombo1Event( HWND hDlg, WPARAM wParam, LPARAM lParam );
|
||||
void SelfHealSetup_fillList( HWND hDlg );
|
||||
void SelfHealSetup_OnApply( HWND hDlg );
|
||||
void SelfHealSetup_OnAdd( HWND hDlg );
|
||||
void SelfHealSetup_OnDel( HWND hDlg );
|
||||
void SelfHealSetup_OnEdit( HWND hDlg );
|
||||
|
||||
INT_PTR CALLBACK EditHealItem_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
HealItem *RS_StartHealItemAdd( HWND hWndParent );
|
||||
BOOL RS_StartHealItemEdit( HWND hWndParent, HealItem *current );
|
||||
|
||||
INT_PTR CALLBACK SelfHealSetup_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: SelfHealSetup_Init( hDlg ); break;
|
||||
case WM_DESTROY: { SelfHealSetup_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_COMBO1: SelfHealSetup_OnCombo1Event( hDlg, wParam, lParam ); break;
|
||||
case IDC_APPLY: SelfHealSetup_OnApply( hDlg ); break;
|
||||
case IDC_DEL: SelfHealSetup_OnDel( hDlg ); break;
|
||||
case IDC_ADD: SelfHealSetup_OnAdd( hDlg ); break;
|
||||
case IDC_EDIT: SelfHealSetup_OnEdit( hDlg ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SelfHealSetup_Init( HWND hDlg )
|
||||
{
|
||||
//log_error( LOG_OK, "init\n" );
|
||||
//SelfHealSetup_saveHWND = hDlg;
|
||||
//
|
||||
rssh_hit = new HealItemsTable();
|
||||
rssh_hit->clear();
|
||||
rssh_hit->LoadFromFile( "L2Detect_healItems.ini" );
|
||||
//
|
||||
HWND h = GetDlgItem( hDlg, IDC_COMBO1 );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("HP Healing") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("MP Healing") );
|
||||
SendMessage( h, CB_ADDSTRING, 0, (LPARAM)TEXT("CP Healing") );
|
||||
SendMessage( h, CB_SETCURSEL, 0, 0 );
|
||||
rssh_cur_sel = 0;
|
||||
//
|
||||
h = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
DWORD dwLvExStyle = LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
|
||||
SendMessage( h, LVM_SETEXTENDEDLISTVIEWSTYLE, (WPARAM)dwLvExStyle, (LPARAM)dwLvExStyle );
|
||||
int i = 0;
|
||||
TCHAR text[256] = {0};
|
||||
LVCOLUMN lvc;
|
||||
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
||||
lvc.cx = 180;
|
||||
lvc.fmt = LVCFMT_LEFT;
|
||||
lvc.iSubItem = i;
|
||||
lvc.pszText = text;
|
||||
lstrcpy( text, TEXT("Item name") );
|
||||
SendMessage( h, LVM_INSERTCOLUMN, i++, (LPARAM)&lvc );
|
||||
lvc.cx = 55;
|
||||
lvc.iSubItem = i;
|
||||
lvc.pszText = text;
|
||||
lstrcpy( text, TEXT("itemID") );
|
||||
SendMessage( h, LVM_INSERTCOLUMN, i++, (LPARAM)&lvc );
|
||||
lvc.cx = 40;
|
||||
lvc.iSubItem = i;
|
||||
lvc.pszText = text;
|
||||
lstrcpy( text, TEXT("pri") );
|
||||
SendMessage( h, LVM_INSERTCOLUMN, i++, (LPARAM)&lvc );
|
||||
lvc.cx = 50;
|
||||
lvc.iSubItem = i;
|
||||
lvc.pszText = text;
|
||||
lstrcpy( text, TEXT("% use") );
|
||||
SendMessage( h, LVM_INSERTCOLUMN, i++, (LPARAM)&lvc );
|
||||
SelfHealSetup_fillList( hDlg );
|
||||
lvc.cx = 70;
|
||||
lvc.iSubItem = i;
|
||||
lvc.pszText = text;
|
||||
lstrcpy( text, TEXT("delay,ms") );
|
||||
SendMessage( h, LVM_INSERTCOLUMN, i++, (LPARAM)&lvc );
|
||||
SelfHealSetup_fillList( hDlg );
|
||||
}
|
||||
|
||||
//void SelfHealSetup_OnOK( HWND hDlg )
|
||||
//{
|
||||
// EndDialog( hDlg, IDOK );
|
||||
//}
|
||||
//
|
||||
//void SelfHealSetup_OnCancel( HWND hDlg )
|
||||
//{
|
||||
// log_error( LOG_OK, "cancel\n" );
|
||||
// EndDialog( hDlg, IDCANCEL );
|
||||
//}
|
||||
|
||||
void SelfHealSetup_OnDestroy( HWND hDlg )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hDlg);
|
||||
rssh_hit->clear();
|
||||
delete rssh_hit;
|
||||
rssh_hit = NULL;
|
||||
//log_error( LOG_OK, "close\n" );
|
||||
}
|
||||
|
||||
void SelfHealSetup_OnCombo1Event( HWND hDlg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
HWND h = GetDlgItem( hDlg, IDC_COMBO1 );
|
||||
int ctrlCode = LOWORD(wParam);
|
||||
int evt = HIWORD(wParam);
|
||||
if( (ctrlCode == IDC_COMBO1) && (evt == CBN_SELCHANGE) )
|
||||
{
|
||||
rssh_cur_sel = (int)SendMessage( h, CB_GETCURSEL, 0, 0 );
|
||||
//log_error( LOG_OK, "CBN_SELCHANGE %d\n", rssh_cur_sel );
|
||||
SelfHealSetup_fillList( hDlg );
|
||||
}
|
||||
}
|
||||
|
||||
void SelfHealSetup_fillList( HWND hDlg )
|
||||
{
|
||||
//CheckDlgButton( hDlg, IDC_C_ENABLED, 0 );
|
||||
switch( rssh_cur_sel )
|
||||
{
|
||||
case 0: CheckDlgButton( hDlg, IDC_C_ENABLED, rssh_hit->enableHealHP ); break;
|
||||
case 1: CheckDlgButton( hDlg, IDC_C_ENABLED, rssh_hit->enableHealMP ); break;
|
||||
case 2: CheckDlgButton( hDlg, IDC_C_ENABLED, rssh_hit->enableHealCP ); break;
|
||||
}
|
||||
HWND h;
|
||||
h = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
SendMessage( h, LVM_DELETEALLITEMS, 0, 0 );
|
||||
HealItem hi;
|
||||
int i;
|
||||
bool bLoop = true;
|
||||
i = 0;
|
||||
LVITEM lvi;
|
||||
int added_item;
|
||||
TCHAR text[256] = {0};
|
||||
lvi.iItem = 0;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = 0;
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
lvi.pszText = text;
|
||||
while( bLoop )
|
||||
{
|
||||
if( rssh_cur_sel == 0 ) bLoop = rssh_hit->getHPItem( i, hi );
|
||||
if( rssh_cur_sel == 1 ) bLoop = rssh_hit->getMPItem( i, hi );
|
||||
if( rssh_cur_sel == 2 ) bLoop = rssh_hit->getCPItem( i, hi );
|
||||
if( !bLoop ) break;
|
||||
//
|
||||
#ifdef UNICODE
|
||||
hi.GetItemNameW( text );
|
||||
#else
|
||||
lstrcpy( text, hi.itemName );
|
||||
#endif
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
lvi.pszText = text;
|
||||
lvi.iItem = 999;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.lParam = i;
|
||||
added_item = (int)SendMessage( h, LVM_INSERTITEM, 0, (LPARAM)&lvi );
|
||||
//
|
||||
lvi.mask = LVIF_TEXT;
|
||||
wsprintf( text, TEXT("%u"), hi.itemID );
|
||||
lvi.lParam = 0;
|
||||
lvi.pszText = text;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 1;
|
||||
SendMessage( h, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
//
|
||||
wsprintf( text, TEXT("%d"), hi.priority );
|
||||
lvi.pszText = text;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 2;
|
||||
SendMessage( h, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
//
|
||||
wsprintf( text, TEXT("%d"), hi.percentUse );
|
||||
lvi.pszText = text;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 3;
|
||||
SendMessage( h, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
//
|
||||
wsprintf( text, TEXT("%u"), hi.reuseDelayMsec );
|
||||
lvi.pszText = text;
|
||||
lvi.iItem = added_item;
|
||||
lvi.iSubItem = 4;
|
||||
SendMessage( h, LVM_SETITEM, 0, (LPARAM)&lvi );
|
||||
//
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void SelfHealSetup_OnApply( HWND hDlg )
|
||||
{
|
||||
//log_error( LOG_OK, "SelfHealSetup_OnApply\n" );
|
||||
int enabled = IsDlgButtonChecked( hDlg, IDC_C_ENABLED );
|
||||
switch( rssh_cur_sel )
|
||||
{
|
||||
case 0: rssh_hit->enableHealHP = enabled; break;
|
||||
case 1: rssh_hit->enableHealMP = enabled; break;
|
||||
case 2: rssh_hit->enableHealCP = enabled; break;
|
||||
}
|
||||
switch( rssh_cur_sel )
|
||||
{
|
||||
case 0: g_game_client->ai.setEnableHealHP( enabled ); break;
|
||||
case 1: g_game_client->ai.setEnableHealMP( enabled ); break;
|
||||
case 2: g_game_client->ai.setEnableHealCP( enabled ); break;
|
||||
}
|
||||
rssh_hit->SaveToFile( "L2Detect_healItems.ini" );
|
||||
g_game_client->ai.setHealItemsTable( rssh_hit );
|
||||
}
|
||||
|
||||
void SelfHealSetup_OnAdd( HWND hDlg )
|
||||
{
|
||||
HealItemsTable::HEALITEM_TYPE hi_type;
|
||||
switch( rssh_cur_sel )
|
||||
{
|
||||
case 0: hi_type = HealItemsTable::HIT_HP; break;
|
||||
case 1: hi_type = HealItemsTable::HIT_MP; break;
|
||||
case 2: hi_type = HealItemsTable::HIT_CP; break;
|
||||
default: return; break;
|
||||
}
|
||||
HealItem *hi = RS_StartHealItemAdd( hDlg );
|
||||
if( hi )
|
||||
{
|
||||
hi->lastUseTime = GetTickCount() - hi->reuseDelayMsec - 1000; // :)
|
||||
rssh_hit->addHealItem( hi_type, hi ); // TODO!
|
||||
SelfHealSetup_fillList( hDlg );
|
||||
delete hi;
|
||||
}
|
||||
}
|
||||
|
||||
void SelfHealSetup_OnDel( HWND hDlg )
|
||||
{
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
int cur_sel = ListView_GetNextItem( hwndLV, -1, LVNI_SELECTED );
|
||||
if( cur_sel == -1 ) return;
|
||||
LVITEM lvi;
|
||||
lvi.iItem = cur_sel;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_PARAM;
|
||||
lvi.lParam = 0;
|
||||
ListView_GetItem( hwndLV, &lvi );
|
||||
ListView_DeleteItem( hwndLV, cur_sel );
|
||||
if( rssh_cur_sel == 0 ) rssh_hit->delItemFromTable( HealItemsTable::HIT_HP, lvi.lParam );
|
||||
if( rssh_cur_sel == 1 ) rssh_hit->delItemFromTable( HealItemsTable::HIT_MP, lvi.lParam );
|
||||
if( rssh_cur_sel == 2 ) rssh_hit->delItemFromTable( HealItemsTable::HIT_CP, lvi.lParam );
|
||||
SelfHealSetup_fillList( hDlg );
|
||||
}
|
||||
|
||||
void SelfHealSetup_OnEdit( HWND hDlg )
|
||||
{
|
||||
HealItemsTable::HEALITEM_TYPE hi_type;
|
||||
switch( rssh_cur_sel )
|
||||
{
|
||||
case 0: hi_type = HealItemsTable::HIT_HP; break;
|
||||
case 1: hi_type = HealItemsTable::HIT_MP; break;
|
||||
case 2: hi_type = HealItemsTable::HIT_CP; break;
|
||||
default: return; break;
|
||||
}
|
||||
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
|
||||
int cur_sel = ListView_GetNextItem( hwndLV, -1, LVNI_SELECTED );
|
||||
if( cur_sel == -1 ) return;
|
||||
LVITEM lvi;
|
||||
lvi.iItem = cur_sel;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.mask = LVIF_PARAM;
|
||||
lvi.lParam = 0;
|
||||
ListView_GetItem( hwndLV, &lvi );
|
||||
int idx = lvi.lParam;
|
||||
HealItem current;
|
||||
switch( rssh_cur_sel )
|
||||
{
|
||||
case 0: rssh_hit->getHPItem( idx, current ); break;
|
||||
case 1: rssh_hit->getMPItem( idx, current ); break;
|
||||
case 2: rssh_hit->getCPItem( idx, current ); break;
|
||||
}
|
||||
if( RS_StartHealItemEdit( hDlg, ¤t ) )
|
||||
{
|
||||
rssh_hit->setHealItem( hi_type, idx, ¤t );
|
||||
SelfHealSetup_fillList( hDlg );
|
||||
}
|
||||
}
|
||||
|
||||
struct RS_HealItemEditStruct
|
||||
{
|
||||
BOOL edit_mode;
|
||||
HealItem *toEdit;
|
||||
};
|
||||
|
||||
HealItem *RS_StartHealItemAdd( HWND hWndParent )
|
||||
{
|
||||
HealItem *current = new HealItem();
|
||||
RS_HealItemEditStruct st;
|
||||
st.edit_mode = FALSE;
|
||||
st.toEdit = current;
|
||||
INT_PTR ret = DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_SELFHEAL_EDITOR),
|
||||
hWndParent, EditHealItem_DlgProc, (LPARAM)&st );
|
||||
if( ret == IDOK ) return current;
|
||||
delete current;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL RS_StartHealItemEdit( HWND hWndParent, HealItem *current )
|
||||
{
|
||||
RS_HealItemEditStruct st;
|
||||
st.edit_mode = TRUE;
|
||||
st.toEdit = current;
|
||||
INT_PTR ret = DialogBoxParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_SELFHEAL_EDITOR),
|
||||
hWndParent, EditHealItem_DlgProc, (LPARAM)&st );
|
||||
if( ret == IDOK ) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK EditHealItem_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
|
||||
struct RS_HealItemEditStruct *st = (struct RS_HealItemEditStruct *)lParam;
|
||||
if( st )
|
||||
{
|
||||
if( st->edit_mode )
|
||||
{
|
||||
SetWindowText( hDlg, TEXT("Edit item") );
|
||||
SetDlgItemTextA( hDlg, IDC_E_ITEMNAME, st->toEdit->itemName );
|
||||
SetDlgItemInt( hDlg, IDC_E_ITEMID, st->toEdit->itemID, FALSE );
|
||||
SetDlgItemInt( hDlg, IDC_E_ITEMPRI, st->toEdit->priority, TRUE );
|
||||
SetDlgItemInt( hDlg, IDC_E_PERCENTUSE, st->toEdit->percentUse, TRUE );
|
||||
SetDlgItemInt( hDlg, IDC_E_REUSEDELAY, st->toEdit->reuseDelayMsec, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowText( hDlg, TEXT("Add item") );
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD( wParam ) )
|
||||
{
|
||||
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
|
||||
case IDOK:
|
||||
{
|
||||
struct RS_HealItemEditStruct *st =
|
||||
(struct RS_HealItemEditStruct *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||||
if( !st )
|
||||
{
|
||||
EndDialog( hDlg, IDCANCEL );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetDlgItemTextA( hDlg, IDC_E_ITEMNAME, st->toEdit->itemName,
|
||||
sizeof(st->toEdit->itemName)-1 );
|
||||
st->toEdit->itemName[sizeof(st->toEdit->itemName)-1] = 0;
|
||||
st->toEdit->itemID = GetDlgItemInt( hDlg, IDC_E_ITEMID, NULL, FALSE );
|
||||
st->toEdit->priority = GetDlgItemInt( hDlg, IDC_E_ITEMPRI, NULL, TRUE );
|
||||
st->toEdit->percentUse = GetDlgItemInt( hDlg, IDC_E_PERCENTUSE, NULL, TRUE );
|
||||
st->toEdit->reuseDelayMsec = GetDlgItemInt( hDlg, IDC_E_REUSEDELAY, NULL, FALSE );
|
||||
EndDialog( hDlg, IDOK );
|
||||
}
|
||||
} break;
|
||||
case IDC_FIND:
|
||||
{
|
||||
Dlg_FindInDB *dlg = new Dlg_FindInDB( Dlg_FindInDB::MODE_ITEM );
|
||||
if( dlg->runDialog( hDlg ) )
|
||||
{
|
||||
//TCHAR tstr[256];
|
||||
//wsprintf( tstr, TEXT("%u: %s"), dlg->itemID, dlg->itemNameW );
|
||||
//MessageBox( hDlg, tstr, TEXT("Result"), 0 );
|
||||
SetDlgItemTextA( hDlg, IDC_E_ITEMNAME, dlg->itemName );
|
||||
SetDlgItemInt( hDlg, IDC_E_ITEMID, dlg->itemID, FALSE );
|
||||
}
|
||||
delete dlg;
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
6
l2detect/RadarSetupDlg_SelfHeal.h
Normal file
6
l2detect/RadarSetupDlg_SelfHeal.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_SelfHeal
|
||||
#define H_RadarSetupDlg_SelfHeal
|
||||
|
||||
HWND RadarSetupDlg_SelfHeal_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
180
l2detect/RadarSetupDlg_SoundAlerts.cpp
Normal file
180
l2detect/RadarSetupDlg_SoundAlerts.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "stdafx.h"
|
||||
#include "Resource.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
|
||||
extern HINSTANCE g_radardll_hinst;
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
INT_PTR CALLBACK SoundAlerts_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
HWND RadarSetupDlg_SoundAlerts_Create( HWND hWndParent )
|
||||
{
|
||||
return CreateDialogParam( g_radardll_hinst, MAKEINTRESOURCE(IDD_SR_SOUNDALERTS),
|
||||
hWndParent, SoundAlerts_DlgProc, 0 );
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
|
||||
void SoundAlerts_Init( HWND hDlg );
|
||||
void SoundAlerts_OnDestroy( HWND hDlg );
|
||||
void SoundAlerts_OnApply( HWND hDlg );
|
||||
void SoundAlerts_OnFind( HWND hDlg, int N );
|
||||
void SoundAlerts_PlayFile( HWND hDlg, int N );
|
||||
|
||||
|
||||
INT_PTR CALLBACK SoundAlerts_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
lParam;
|
||||
switch( uMsg )
|
||||
{
|
||||
case WM_INITDIALOG: SoundAlerts_Init( hDlg ); break;
|
||||
case WM_DESTROY: { SoundAlerts_OnDestroy( hDlg ); return FALSE; } break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDC_APPLY: SoundAlerts_OnApply( hDlg ); break;
|
||||
case IDC_B_FIND1: SoundAlerts_OnFind( hDlg, 1 ); break;
|
||||
case IDC_B_FIND2: SoundAlerts_OnFind( hDlg, 2 ); break;
|
||||
case IDC_B_FIND3: SoundAlerts_OnFind( hDlg, 3 ); break;
|
||||
case IDC_B_PLAY1: SoundAlerts_PlayFile( hDlg, 1 ); break;
|
||||
case IDC_B_PLAY2: SoundAlerts_PlayFile( hDlg, 2 ); break;
|
||||
case IDC_B_PLAY3: SoundAlerts_PlayFile( hDlg, 3 ); break;
|
||||
}
|
||||
} break;
|
||||
default: return FALSE; break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SoundAlerts_Init( HWND hDlg )
|
||||
{
|
||||
// force UserAI to reload config file
|
||||
g_game_client->ai.loadSoundAlertsCfgFromFile();
|
||||
//
|
||||
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_SOUNDTYPECW );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Info") );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Warning") );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Critical") );
|
||||
hwndCB = GetDlgItem( hDlg, IDC_CB_SOUNDTYPETARGET );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Info") );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Warning") );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Critical") );
|
||||
hwndCB = GetDlgItem( hDlg, IDC_CB_SOUNDTYPEINVISGM );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Info") );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Warning") );
|
||||
SendMessage( hwndCB, CB_ADDSTRING, 0, (LPARAM)TEXT("Critical") );
|
||||
// set initial CB checks
|
||||
if( g_game_client->ai.soundAlert_alertOnClanWar > 0 )
|
||||
{
|
||||
CheckDlgButton( hDlg, IDC_C_SOUNDENEMYENTER, g_game_client->ai.soundAlert_alertOnClanWar );
|
||||
hwndCB = GetDlgItem( hDlg, IDC_CB_SOUNDTYPECW );
|
||||
ComboBox_SetCurSel( hwndCB, g_game_client->ai.soundAlert_alertOnClanWar - 1 );
|
||||
}
|
||||
if( g_game_client->ai.soundAlert_alertOnTargeted > 0 )
|
||||
{
|
||||
CheckDlgButton( hDlg, IDC_C_SOUNDWHENTARGETED, g_game_client->ai.soundAlert_alertOnTargeted );
|
||||
hwndCB = GetDlgItem( hDlg, IDC_CB_SOUNDTYPETARGET );
|
||||
ComboBox_SetCurSel( hwndCB, g_game_client->ai.soundAlert_alertOnTargeted - 1 );
|
||||
}
|
||||
if( g_game_client->ai.soundAlert_alertOnInvisGM > 0 )
|
||||
{
|
||||
CheckDlgButton( hDlg, IDC_C_SOUNDONINVISGM, g_game_client->ai.soundAlert_alertOnTargeted );
|
||||
hwndCB = GetDlgItem( hDlg, IDC_CB_SOUNDTYPEINVISGM );
|
||||
ComboBox_SetCurSel( hwndCB, g_game_client->ai.soundAlert_alertOnInvisGM - 1 );
|
||||
}
|
||||
// no clan/party alert, screen message
|
||||
CheckDlgButton( hDlg, IDC_C_NOPARTYTARGETALERT, g_game_client->ai.soundAlert_noPartyTargetAlert );
|
||||
CheckDlgButton( hDlg, IDC_C_NOCLANTARGETALERT, g_game_client->ai.soundAlert_noClanTargetAlert );
|
||||
CheckDlgButton( hDlg, IDC_C_TARGETALERTONSCREEN, g_game_client->ai.soundAlert_screenMessage );
|
||||
// set file names
|
||||
SetDlgItemTextA( hDlg, IDC_E_VERYCRITICALFILE, g_game_client->ai.soundAlert_fileNameCritical );
|
||||
SetDlgItemTextA( hDlg, IDC_E_WARNINGFILE, g_game_client->ai.soundAlert_fileNameWarning );
|
||||
SetDlgItemTextA( hDlg, IDC_E_INFOFILE, g_game_client->ai.soundAlert_fileNameInfo );
|
||||
}
|
||||
|
||||
|
||||
void SoundAlerts_OnDestroy( HWND hDlg )
|
||||
{
|
||||
hDlg;
|
||||
//log_error( LOG_OK, "SoundAlerts_OnDestroy\n" );
|
||||
}
|
||||
|
||||
void SoundAlerts_OnApply( HWND hDlg )
|
||||
{
|
||||
//log_error( LOG_OK, "SoundAlerts_OnApply\n" );
|
||||
// apply dialog config to UserAI class
|
||||
HWND hwndcb = NULL;
|
||||
if( IsDlgButtonChecked( hDlg, IDC_C_SOUNDENEMYENTER ) )
|
||||
{
|
||||
hwndcb = GetDlgItem( hDlg, IDC_CB_SOUNDTYPECW );
|
||||
g_game_client->ai.soundAlert_alertOnClanWar = 1 + ComboBox_GetCurSel( hwndcb );
|
||||
}
|
||||
else g_game_client->ai.soundAlert_alertOnClanWar = 0;
|
||||
//
|
||||
if( IsDlgButtonChecked( hDlg, IDC_C_SOUNDWHENTARGETED ) )
|
||||
{
|
||||
hwndcb = GetDlgItem( hDlg, IDC_CB_SOUNDTYPETARGET );
|
||||
g_game_client->ai.soundAlert_alertOnTargeted = 1 + ComboBox_GetCurSel( hwndcb );
|
||||
}
|
||||
else g_game_client->ai.soundAlert_alertOnTargeted = 0;
|
||||
//
|
||||
if( IsDlgButtonChecked( hDlg, IDC_C_SOUNDONINVISGM ) )
|
||||
{
|
||||
hwndcb = GetDlgItem( hDlg, IDC_CB_SOUNDTYPEINVISGM );
|
||||
g_game_client->ai.soundAlert_alertOnInvisGM = 1 + ComboBox_GetCurSel( hwndcb );
|
||||
}
|
||||
else g_game_client->ai.soundAlert_alertOnInvisGM = 0;
|
||||
// no clan/party alert, screen message
|
||||
g_game_client->ai.soundAlert_noPartyTargetAlert = IsDlgButtonChecked( hDlg, IDC_C_NOPARTYTARGETALERT );
|
||||
g_game_client->ai.soundAlert_noClanTargetAlert = IsDlgButtonChecked( hDlg, IDC_C_NOCLANTARGETALERT );
|
||||
g_game_client->ai.soundAlert_screenMessage = IsDlgButtonChecked( hDlg, IDC_C_TARGETALERTONSCREEN );
|
||||
// file names
|
||||
GetDlgItemTextA( hDlg, IDC_E_VERYCRITICALFILE, g_game_client->ai.soundAlert_fileNameCritical, 255 );
|
||||
GetDlgItemTextA( hDlg, IDC_E_WARNINGFILE, g_game_client->ai.soundAlert_fileNameWarning, 255 );
|
||||
GetDlgItemTextA( hDlg, IDC_E_INFOFILE, g_game_client->ai.soundAlert_fileNameInfo, 255 );
|
||||
// save to file
|
||||
g_game_client->ai.saveSoundAlertsCfgToFile();
|
||||
}
|
||||
|
||||
void SoundAlerts_OnFind( HWND hDlg, int N )
|
||||
{
|
||||
TCHAR fileName[256] = {0};
|
||||
OPENFILENAME ofn;
|
||||
memset( &ofn, 0, sizeof(ofn) );
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.Flags = OFN_EXPLORER | OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;
|
||||
ofn.hInstance = g_radardll_hinst;
|
||||
ofn.hwndOwner = hDlg;
|
||||
ofn.lpstrFile = fileName;
|
||||
ofn.lpstrTitle = TEXT("Choose sound file:");
|
||||
ofn.nMaxFile = 255;
|
||||
if( GetOpenFileName( &ofn ) )
|
||||
{
|
||||
//MessageBox( hDlg, fileName, TEXT("User choosed"), 0 );
|
||||
switch( N )
|
||||
{
|
||||
case 1: SetDlgItemText( hDlg, IDC_E_VERYCRITICALFILE, fileName ); break;
|
||||
case 2: SetDlgItemText( hDlg, IDC_E_WARNINGFILE, fileName ); break;
|
||||
case 3: SetDlgItemText( hDlg, IDC_E_INFOFILE, fileName ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundAlerts_PlayFile( HWND hDlg, int N )
|
||||
{
|
||||
TCHAR text[256] = {0};
|
||||
if( N<1 || N>3 ) return;
|
||||
switch( N )
|
||||
{
|
||||
case 1: GetDlgItemText( hDlg, IDC_E_VERYCRITICALFILE, text, 255 ); break;
|
||||
case 2: GetDlgItemText( hDlg, IDC_E_WARNINGFILE, text, 255 ); break;
|
||||
case 3: GetDlgItemText( hDlg, IDC_E_INFOFILE, text, 255 ); break;
|
||||
}
|
||||
if( !PlaySound( text, NULL, SND_FILENAME | SND_ASYNC ) )
|
||||
{
|
||||
ErrorLogger_LogLastError( "PlaySoundW", GetLastError() );
|
||||
MessageBox( hDlg, TEXT("PlaySound() failed"), text, MB_ICONSTOP );
|
||||
}
|
||||
}
|
||||
6
l2detect/RadarSetupDlg_SoundAlerts.h
Normal file
6
l2detect/RadarSetupDlg_SoundAlerts.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_RadarSetupDlg_SoundAlerts
|
||||
#define H_RadarSetupDlg_SoundAlerts
|
||||
|
||||
HWND RadarSetupDlg_SoundAlerts_Create( HWND hWndParent );
|
||||
|
||||
#endif
|
||||
62
l2detect/RemoteServerInfo.cpp
Normal file
62
l2detect/RemoteServerInfo.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "stdafx.h"
|
||||
#include "RemoteServerInfo.h"
|
||||
|
||||
RemoteServerInfo::RemoteServerInfo(void)
|
||||
{
|
||||
_tcscpy( str_desc, TEXT("[no_desc]") );
|
||||
strcpy( str_ip, "0.0.0.0" );
|
||||
memset( m_desc, 0, sizeof(m_desc) );
|
||||
memset( m_ip, 0, sizeof(m_ip) );
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
RemoteServerInfo::RemoteServerInfo( const RemoteServerInfo& other )
|
||||
{
|
||||
this->setDesc( other.desc() );
|
||||
this->setIP( other.ip() );
|
||||
this->setPort( other.port() );
|
||||
}
|
||||
|
||||
RemoteServerInfo &RemoteServerInfo::operator=( const RemoteServerInfo& other )
|
||||
{
|
||||
this->setDesc( other.desc() );
|
||||
this->setIP( other.ip() );
|
||||
this->setPort( other.port() );
|
||||
return (*this);
|
||||
}
|
||||
|
||||
RemoteServerInfo::~RemoteServerInfo(void)
|
||||
{
|
||||
m_desc[0] = 0;
|
||||
m_ip[0] = 0;
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
|
||||
LPCTSTR RemoteServerInfo::desc() const
|
||||
{
|
||||
if( m_desc[0] == 0 ) return str_desc;
|
||||
((RemoteServerInfo *)this)->m_desc[127] = 0; // close string for sure
|
||||
return m_desc;
|
||||
}
|
||||
|
||||
const char *RemoteServerInfo::ip() const
|
||||
{
|
||||
if( m_ip[0] == 0 ) return str_ip;
|
||||
((RemoteServerInfo *)this)->m_ip[15] = 0; // close string for sure
|
||||
return m_ip;
|
||||
}
|
||||
|
||||
void RemoteServerInfo::setDesc( LPCTSTR desc )
|
||||
{
|
||||
m_desc[0] = 0;
|
||||
if( !desc ) return;
|
||||
_tcsncpy( m_desc, desc, 127 );
|
||||
}
|
||||
|
||||
void RemoteServerInfo::setIP( const char *ip )
|
||||
{
|
||||
m_ip[0] = 0;
|
||||
if( !ip ) return;
|
||||
strncpy( m_ip, ip, 15 );
|
||||
}
|
||||
28
l2detect/RemoteServerInfo.h
Normal file
28
l2detect/RemoteServerInfo.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _H_REMOTESERVERINFO
|
||||
#define _H_REMOTESERVERINFO
|
||||
|
||||
class RemoteServerInfo
|
||||
{
|
||||
public:
|
||||
RemoteServerInfo();
|
||||
RemoteServerInfo( const RemoteServerInfo& other );
|
||||
RemoteServerInfo &operator=( const RemoteServerInfo& other );
|
||||
virtual ~RemoteServerInfo();
|
||||
public:
|
||||
LPCTSTR desc() const;
|
||||
const char *ip() const;
|
||||
unsigned short port() const { return m_port; }
|
||||
public:
|
||||
void setDesc( LPCTSTR desc );
|
||||
void setIP( const char *ip );
|
||||
void setPort( unsigned short int port ) { m_port = port; }
|
||||
protected:
|
||||
TCHAR m_desc[128];
|
||||
char m_ip[16];
|
||||
unsigned short int m_port;
|
||||
protected:
|
||||
TCHAR str_desc[32];
|
||||
char str_ip[16];
|
||||
};
|
||||
|
||||
#endif /* _H_REMOTESERVERINFO */
|
||||
183
l2detect/Resource.h
Normal file
183
l2detect/Resource.h
Normal file
@@ -0,0 +1,183 @@
|
||||
// Used by L2Detect.rc
|
||||
|
||||
#define IDM_ABOUTBOX 0x0010
|
||||
#define IDD_ABOUTBOX 100
|
||||
#define IDD_CONFIG 129
|
||||
#define IDD_DEBUG 133
|
||||
#define IDD_SETUPRADAR 134
|
||||
#define IDD_SR_SELFHEAL 135
|
||||
#define IDI_MFC 136
|
||||
#define IDI_L2_GREEN 137
|
||||
#define IDI_L2_BLACK 138
|
||||
#define IDI_L2_PURPLE 139
|
||||
#define IDD_SR_SELFHEAL_EDITOR 140
|
||||
#define IDD_SR_FINDINDB 141
|
||||
#define IDD_SR_OFFPARTYBDSWS 142
|
||||
#define IDI_L2_BLUE 143
|
||||
#define IDD_SR_SOUNDALERTS 144
|
||||
#define IDI_RED_CIRCLE 145
|
||||
#define IDI_GREEN_CIRCLE 146
|
||||
#define IDI_CROSS 147
|
||||
#define IDD_SR_COLORS 148
|
||||
#define IDI_RED_HALF_CIRCLE 149
|
||||
#define IDD_SR_INVISGM 150
|
||||
#define IDD_SR_QUICKTARGET 151
|
||||
#define IDD_PRESSKEY 152
|
||||
#define IDD_SR_DISTPRI 153
|
||||
#define IDD_SR_DISTPRI_EDITPRI 154
|
||||
#define IDD_SR_FOLLOWASSIST 155
|
||||
#define IDD_SR_LOCKTARGET 156
|
||||
|
||||
#define IDC_ELLSTATUS 1020
|
||||
#define IDC_EGLSTATUS 1021
|
||||
#define IDC_STARTLL 1022
|
||||
#define IDC_STARTGL 1023
|
||||
#define IDC_STOPLL 1024
|
||||
#define IDC_STOPGL 1025
|
||||
#define IDC_FLUSH_LOG 1027
|
||||
#define IDC_C_ENABLE_MODGT 1028
|
||||
#define IDC_C_ENABLE_THREADPRI 1029
|
||||
#define IDC_E_OVERRIDE_GPV 1030
|
||||
#define IDC_HP 1032
|
||||
#define IDC_MP 1033
|
||||
#define IDC_CP 1034
|
||||
#define IDC_CHARNAME 1035
|
||||
#define IDC_CB_LOGLEVEL 1036
|
||||
#define IDC_B_CONENABLE 1037
|
||||
#define IDC_B_CONDISABLE 1038
|
||||
#define IDC_C_L2WMOVEFIX 1039
|
||||
#define IDC_E_FLPORT 1040
|
||||
#define IDC_E_FGPORT 1041
|
||||
#define IDC_E_REALIP 1042
|
||||
#define IDC_E_REALPORT 1043
|
||||
#define IDC_E_PLAYGSNO 1044
|
||||
#define IDC_APPLY 1045
|
||||
#define IDC_C_LOGGAMEP 1046
|
||||
#define IDC_ENABLE 1046
|
||||
#define IDC_E_LOGFNPREFIX 1047
|
||||
#define IDC_APPLY2 1047
|
||||
#define IDC_SAVE 1047
|
||||
#define IDC_CB_L2VER 1048
|
||||
#define IDC_T_CONFIG 1049
|
||||
#define IDC_CB_L2CVER 1049
|
||||
#define IDC_C_L2WDROPGMLIST 1050
|
||||
#define IDC_C_L2WSITFIX 1051
|
||||
#define IDC_B_LOAD 1052
|
||||
#define IDC_B_SAVE 1053
|
||||
#define IDC_C_WARNUNKP 1054
|
||||
#define IDC_NPSETUP 1055
|
||||
#define IDC_LISTITEMS 1056
|
||||
#define IDC_COMBO1 1057
|
||||
#define IDC_C_ENABLED 1058
|
||||
#define IDC_ADD 1059
|
||||
#define IDC_EDIT 1060
|
||||
#define IDC_DEL 1061
|
||||
#define IDC_E_ITEMNAME 1063
|
||||
#define IDC_E_ITEMID 1064
|
||||
#define IDC_E_ITEMPRI 1065
|
||||
#define IDC_E_PERCENTUSE 1066
|
||||
#define IDC_E_REUSEDELAY 1067
|
||||
#define IDC_EDITNAME 1071
|
||||
#define IDC_R_STWITH 1072
|
||||
#define IDC_R_CONTAINS 1073
|
||||
#define IDC_R_ENWITH 1074
|
||||
#define IDC_FIND 1077
|
||||
#define IDC_C_INVBD 1079
|
||||
#define IDC_E_BDNAME 1080
|
||||
#define IDC_E_INV_BD_SEC 1081
|
||||
#define IDC_E_DISMISS_BD_SEC 1082
|
||||
#define IDC_C_INVSWS 1083
|
||||
#define IDC_E_SWSNAME 1084
|
||||
#define IDC_E_INV_SWS_SEC 1085
|
||||
#define IDC_E_DISMISS_SWS_SEC 1086
|
||||
#define IDC_E_FORCEGSIP 1087
|
||||
#define IDC_E_FORCEGSPORT 1088
|
||||
#define IDC_B_VALIDATEINTERCEPT 1089
|
||||
#define IDC_B_INTERCEPTCONNECT 1090
|
||||
#define IDC_B_CHECK_VIRTUALPROTECTEX 1091
|
||||
#define IDC_C_L2WALKER_INJECTSTATUSUPDATE 1122
|
||||
#define IDC_B_LOADWALKER 1123
|
||||
#define IDC_B_UNLOADWALKER 1124
|
||||
#define IDC_C_GAMEGUARDREPLY 1125
|
||||
#define IDC_C_EPILOGUE_148_146 1126
|
||||
#define IDC_B_DUMP_ALL_RELATIONS 1127
|
||||
#define IDC_B_PRINTADDRTID 1128
|
||||
|
||||
// radar sound alerts setup dlg
|
||||
#define IDC_C_SOUNDENEMYENTER 1089
|
||||
#define IDC_C_SOUNDWHENTARGETED 1090
|
||||
#define IDC_CB_SOUNDTYPECW 1091
|
||||
#define IDC_CB_SOUNDTYPETARGET 1092
|
||||
#define IDC_B_FIND1 1093
|
||||
#define IDC_B_FIND2 1094
|
||||
#define IDC_B_FIND3 1095
|
||||
#define IDC_E_VERYCRITICALFILE 1096
|
||||
#define IDC_E_WARNINGFILE 1097
|
||||
#define IDC_E_INFOFILE 1098
|
||||
#define IDC_C_NOPARTYTARGETALERT 1099
|
||||
#define IDC_C_NOCLANTARGETALERT 1100
|
||||
#define IDC_C_TARGETALERTONSCREEN 1101
|
||||
#define IDC_CB_SOUNDTYPEINVISGM 1102
|
||||
#define IDC_C_SOUNDONINVISGM 1103
|
||||
#define IDC_B_PLAY1 1104
|
||||
#define IDC_B_PLAY2 1105
|
||||
#define IDC_B_PLAY3 1106
|
||||
|
||||
// radar color setup dlg
|
||||
#define IDC_B_SELNPCCOLOR 1110
|
||||
#define IDC_B_SELMOBCOLOR 1111
|
||||
#define IDC_B_SELPLAYERCOLOR 1112
|
||||
#define IDC_B_SELDEADPLAYERCOLOR 1113
|
||||
#define IDC_B_SELPARTYPLAYERCOLOR 1114
|
||||
#define IDC_B_SELDEADPARTYPLAYERCOLOR 1115
|
||||
#define IDC_B_SELENEMYPLAYERCOLOR 1116
|
||||
#define IDC_B_SELDEADENEMYPLAYERCOLOR 1117
|
||||
|
||||
// radar invis gm setup dlg
|
||||
#define IDC_C_INVIS_GM_ENABLE 1120
|
||||
#define IDC_E_INVIS_GM_SPEED 1121
|
||||
|
||||
// radar quicktarget setup dlg
|
||||
#define IDC_E_KEY 1122
|
||||
#define IDC_B_SET_TARGET_KEY 1123
|
||||
//#define IDC_C_DONT_TARGET_DEAD 1124
|
||||
//#define IDC_C_DONT_TARGET_PARTY 1125
|
||||
//#define IDC_C_DONT_TARGET_CLAN 1126
|
||||
//#define IDC_C_DONT_TARGET_ALLY 1127
|
||||
//#define IDC_B_UP 1128
|
||||
//#define IDC_B_DOWN 1129
|
||||
#define IDC_CLASSLIST 1130
|
||||
#define IDC_E_MAXDIST 1131
|
||||
//#define IDC_R_TARGET_NEAREST 1132
|
||||
//#define IDC_R_USE_ONLY_PRIORITY 1133
|
||||
//#define IDC_R_USE_BOTH 1134
|
||||
//#define IDC_C_TARGET_ONLY_CW 1135
|
||||
//#define IDC_C_TARGET_ALSO_PK 1136
|
||||
//#define IDC_C_TARGET_ALSO_FLAGGED 1137
|
||||
#define IDC_C_SHOUT_TARGET_IN_PARTY_CHAT 1138
|
||||
#define IDC_B_DISTANCE_SETUP 1139
|
||||
#define IDC_TAB1 1140
|
||||
// distance setup dialog
|
||||
#define IDC_B_ADD 1140
|
||||
#define IDC_B_EDIT 1141
|
||||
#define IDC_B_DEL 1142
|
||||
#define IDC_LIST1 1143
|
||||
#define IDC_E_MIN 1144
|
||||
#define IDC_E_MAX 1145
|
||||
#define IDC_E_PRI 1146
|
||||
|
||||
// follow & assist dialog
|
||||
#define IDC_C_FOLLOW_ENABLE 1150
|
||||
#define IDC_C_ASSIST_ENABLE 1151
|
||||
#define IDC_E_NAME_FOLLOW 1152
|
||||
#define IDC_E_NAME_ASSIST 1153
|
||||
#define IDC_C_FOLLOW_ONLY_IN_PARTY 1154
|
||||
#define IDC_C_ASSIST_ONLY_IN_PARTY 1155
|
||||
#define IDC_C_DONT_ASSIST_ALLIES 1156
|
||||
#define IDC_E_FOLLOW_DISTANCE 1157
|
||||
|
||||
// lock target setup dialog
|
||||
#define IDC_C_LT_ENABLED 1200
|
||||
|
||||
#define ID_DEBUGDLG 32773
|
||||
|
||||
315
l2detect/ScriptEngine.cpp
Normal file
315
l2detect/ScriptEngine.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
#include "stdafx.h"
|
||||
#include "Logger.h"
|
||||
#include "lua/lua.hpp"
|
||||
#include "GameClient.h"
|
||||
#include "PacketInjector.h"
|
||||
#include "se_funcs/SE_funcs.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
extern class GameClient *g_game_client; // in main.cpp
|
||||
|
||||
ScriptEngine *ScriptEngine::s_instance = NULL;
|
||||
int ScriptEngine::s_refCount = 0;
|
||||
|
||||
ScriptEngine *ScriptEngine::getInstance()
|
||||
{
|
||||
if( ScriptEngine::s_instance == NULL )
|
||||
{
|
||||
ScriptEngine::s_instance = new ScriptEngine();
|
||||
ScriptEngine::s_refCount++;
|
||||
log_error( LOG_DEBUG, "ScriptEngine: created instance\n" );
|
||||
}
|
||||
return ScriptEngine::s_instance;
|
||||
}
|
||||
|
||||
void ScriptEngine::freeInstance()
|
||||
{
|
||||
if( ScriptEngine::s_refCount > 0 )
|
||||
{
|
||||
ScriptEngine::s_refCount--;
|
||||
if( ScriptEngine::s_refCount == 0 )
|
||||
{
|
||||
delete ScriptEngine::s_instance;
|
||||
ScriptEngine::s_instance = NULL;
|
||||
log_error( LOG_DEBUG, "ScriptEngine: freed instance\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScriptEngine::ScriptEngine()
|
||||
{
|
||||
L = NULL;
|
||||
hThread = NULL;
|
||||
memset( script_fileName, 0, sizeof(script_fileName) );
|
||||
should_stop = false;
|
||||
_isPaused = false;
|
||||
// handlers
|
||||
m_onChat_enabled = false;
|
||||
m_onChat_functionName[0] = 0;
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
void ScriptEngine::init()
|
||||
{
|
||||
if( !L )
|
||||
{
|
||||
L = luaL_newstate(); // open Lua virtual machine
|
||||
if( L )
|
||||
{
|
||||
luaL_openlibs( L ); // load the Lua libraries: math, io, ..
|
||||
SE_funcs_register( L ); // register main functions (l2h_*)
|
||||
}
|
||||
else log_error( LOG_ERROR, "ScriptEngine::init(): luaL_newstate() returned NULL!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::deinit()
|
||||
{
|
||||
if( L )
|
||||
{
|
||||
lua_close( L ); // Destroys all objects in the given Lua state
|
||||
//(calling the corresponding garbage-collection metamethods, if any)
|
||||
//and frees all dynamic memory used by this state
|
||||
L = NULL;
|
||||
if( hThread ) CloseHandle( hThread );
|
||||
hThread = NULL;
|
||||
should_stop = false;
|
||||
_isPaused = false;
|
||||
// handlers
|
||||
m_onChat_enabled = false;
|
||||
m_onChat_functionName[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::getLastFileName( char *out )
|
||||
{
|
||||
if( !out ) return;
|
||||
out[0] = 0;
|
||||
if( script_fileName[0] != 0 ) strcpy( out, script_fileName );
|
||||
}
|
||||
|
||||
void ScriptEngine::startScriptThread( const char *filename /*= NULL */ )
|
||||
{
|
||||
if( hThread ) return;
|
||||
DWORD dwThreadID = 0;
|
||||
if( filename ) strcpy( script_fileName, filename );
|
||||
hThread = (HANDLE)_beginthreadex( NULL, 0,
|
||||
(unsigned int (__stdcall *)(void *))scriptEngineThread, (void *)this,
|
||||
0, (unsigned int *)&dwThreadID );
|
||||
}
|
||||
|
||||
bool ScriptEngine::stopScriptThread( DWORD dwTimeoutMsec, bool bTerminate )
|
||||
{
|
||||
if( !hThread ) return true;
|
||||
this->should_stop = true; // "signal" to stop )
|
||||
DWORD wait_res = WaitForSingleObject( hThread, dwTimeoutMsec );
|
||||
if( wait_res != WAIT_OBJECT_0 ) // wait failed :(
|
||||
{
|
||||
if( !bTerminate ) return false; // do not do anything, just ret false
|
||||
TerminateThread( hThread, 0 );
|
||||
log_error( LOG_ERROR, "ScriptEngine::stopScriptThread(): script thread wait failed, TERMINATED!\n" );
|
||||
this->deinit();
|
||||
this->set_onChat_handler( NULL ); // disable onChat() handler
|
||||
this->init();
|
||||
if( L ) log_error( LOG_WARNING, "ScriptEngine::stopScriptThread(): re-initialized ScriptEngine, bugs possible ><\n" );
|
||||
}
|
||||
if( hThread ) CloseHandle( hThread ); // cleanup
|
||||
hThread = NULL;
|
||||
this->should_stop = false; // no more need to stop...
|
||||
return true;
|
||||
}
|
||||
|
||||
int ScriptEngine::isScriptThreadRunning() const
|
||||
{
|
||||
if( hThread == NULL ) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ScriptEngine::isScriptThreadPaused() const
|
||||
{
|
||||
if( _isPaused ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ScriptEngine::pauseScriptThread( bool bPause /*= true*/ )
|
||||
{
|
||||
if( !isScriptThreadRunning() ) return false;
|
||||
int prev_suspend_count = 0;
|
||||
if( bPause )
|
||||
{
|
||||
prev_suspend_count = (int)SuspendThread( hThread );
|
||||
if( prev_suspend_count > 0 )
|
||||
{
|
||||
log_error( LOG_WARNING, "ScriptEngine::pauseScriptThread(): PAUSE: thread was already suspended, resuming again\n" );
|
||||
ResumeThread( hThread );
|
||||
}
|
||||
_isPaused = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_suspend_count = ResumeThread( hThread );
|
||||
if( prev_suspend_count > 1 )
|
||||
{
|
||||
log_error( LOG_WARNING, "ScriptEngine::pauseScriptThread(): UNPAUSE: possible that thread is still suspended!\n" );
|
||||
}
|
||||
_isPaused = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD WINAPI ScriptEngine::scriptEngineThread( LPVOID lpvClass )
|
||||
{
|
||||
if( !lpvClass ) return 0;
|
||||
ScriptEngine *pcls = (ScriptEngine *)lpvClass;
|
||||
|
||||
// run a Lua script here
|
||||
int r = luaL_loadfile( pcls->L, pcls->script_fileName );
|
||||
if( r == 0 )
|
||||
{
|
||||
log_error( LOG_DEBUG, "SE: file [%s] loaded.\n", pcls->script_fileName );
|
||||
// Call main...
|
||||
try
|
||||
{
|
||||
r = lua_pcall( pcls->L, 0, LUA_MULTRET, 0 );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
log_error( LOG_ERROR, "SE: catched C++ exception after lua_pcall()\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
}
|
||||
|
||||
if( r == 0 ) log_error( LOG_DEBUG, "SE: run OK\n" );
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "SE: file [%s] lua_pcall() error %d\n", pcls->script_fileName, r );
|
||||
switch( r )
|
||||
{
|
||||
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
|
||||
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
|
||||
case LUA_ERRSYNTAX: log_error( LOG_ERROR, "SE: LUA_ERRSYNTAX\n" ); break;
|
||||
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
|
||||
}
|
||||
int nArgs = lua_gettop( pcls->L );
|
||||
if( nArgs >= 1 )
|
||||
{
|
||||
if( lua_isstring( pcls->L, 1 ) )
|
||||
log_error( LOG_ERROR, "SE: [%s]\n", lua_tolstring( pcls->L, 1, NULL ) );
|
||||
}
|
||||
lua_settop( pcls->L, 0 ); // clear stack
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error( LOG_ERROR, "SE: file [%s] luaL_loadfile() error %d\n", pcls->script_fileName, r );
|
||||
switch( r )
|
||||
{
|
||||
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
|
||||
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
|
||||
case LUA_ERRSYNTAX: log_error( LOG_ERROR, "SE: LUA_ERRSYNTAX\n" ); break;
|
||||
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
|
||||
case LUA_ERRFILE: log_error( LOG_ERROR, "SE: LUA_ERRFILE\n" ); break;
|
||||
}
|
||||
int nArgs = lua_gettop( pcls->L );
|
||||
if( nArgs >= 1 )
|
||||
{
|
||||
if( lua_isstring( pcls->L, 1 ) )
|
||||
{
|
||||
log_error( LOG_ERROR, "SE: [%s]\n", lua_tolstring( pcls->L, 1, NULL ) );
|
||||
//lua_pop( pcls->L, 1 ); // really?
|
||||
}
|
||||
}
|
||||
lua_settop( pcls->L, 0 ); // clear stack
|
||||
}
|
||||
pcls->set_onChat_handler( NULL ); // disable onChat() handler
|
||||
if( pcls->hThread ) CloseHandle( pcls->hThread ); // cleanup
|
||||
pcls->hThread = NULL; // mark thread as not running
|
||||
pcls->should_stop = false;
|
||||
log_error( LOG_DEBUG, "SE: scriptEngineThread() stopped [%s]\n", pcls->script_fileName );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// http://www.lua.ru/doc/3.7.html
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> Lua:
|
||||
// a = f('how', t.x, 14)
|
||||
//
|
||||
//<2F><> <20><> <20> C:
|
||||
// lua_getfield(L, LUA_GLOBALSINDEX, 'f'); /* function to be called */
|
||||
// lua_pushstring(L, 'how'); /* 1st argument */
|
||||
// lua_getfield(L, LUA_GLOBALSINDEX, 't'); /* table to be indexed */
|
||||
// lua_getfield(L, -1, 'x'); /* push result of t.x (2nd arg) */
|
||||
// lua_remove(L, -2); /* remove 't' from the stack */
|
||||
// lua_pushinteger(L, 14); /* 3rd argument */
|
||||
// lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */
|
||||
// lua_setfield(L, LUA_GLOBALSINDEX, 'a'); /* set global 'a' */
|
||||
//
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
|
||||
void ScriptEngine::call_onChat( unsigned int senderObjectId, int channelId, const wchar_t *message, const wchar_t *from )
|
||||
{
|
||||
if( !m_onChat_enabled ) return;
|
||||
if( !message ) return;
|
||||
if( !isScriptThreadRunning() ) return;
|
||||
if( isScriptThreadPaused() ) return;
|
||||
//
|
||||
pauseScriptThread( true ); // pause script thread
|
||||
//
|
||||
// convert strings from Unicode to ANSI
|
||||
char message_ansi[1024];
|
||||
char from_ansi[128];
|
||||
message_ansi[0] = from_ansi[0] = 0;
|
||||
WideCharToMultiByte( CP_ACP, 0, message, -1, message_ansi, sizeof(message_ansi)-1, NULL, NULL );
|
||||
if( from ) WideCharToMultiByte( CP_ACP, 0, from, -1, from_ansi, sizeof(from_ansi)-1, NULL, NULL );
|
||||
message_ansi[sizeof(message_ansi)-1] = 0;
|
||||
from_ansi[sizeof(from_ansi)-1] = 0;
|
||||
//
|
||||
lua_getfield( L, LUA_GLOBALSINDEX, m_onChat_functionName ); // function to be called
|
||||
lua_pushinteger( L, senderObjectId ); // param 1 - sender object ID
|
||||
lua_pushinteger( L, channelId ); // param 2 - channel ID
|
||||
lua_pushstring( L, message_ansi ); // param 3 - chat message
|
||||
lua_pushstring( L, from_ansi ); // param 4 - sender name (only for PM)
|
||||
// call onChat with 4 arguments and 0 return values: onChat( senderObjectId, channelId, message, from )
|
||||
int ret = lua_pcall( L, 4, 0, 0 );
|
||||
if( ret != 0 )
|
||||
{
|
||||
log_error( LOG_ERROR, "SE: call_onChat() [%s] error %d\n", script_fileName, ret );
|
||||
switch( ret )
|
||||
{
|
||||
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
|
||||
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
|
||||
case LUA_ERRSYNTAX: log_error( LOG_ERROR, "SE: LUA_ERRSYNTAX\n" ); break;
|
||||
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
|
||||
case LUA_ERRFILE: log_error( LOG_ERROR, "SE: LUA_ERRFILE\n" ); break;
|
||||
}
|
||||
int nArgs = lua_gettop( L );
|
||||
if( nArgs >= 1 )
|
||||
{
|
||||
if( lua_isstring( L, 1 ) )
|
||||
log_error( LOG_ERROR, "SE: [%s]\n", lua_tolstring( L, 1, NULL ) );
|
||||
}
|
||||
lua_settop( L, 0 ); // clear stack
|
||||
}
|
||||
else log_error( LOG_DEBUG, "SE: call_onChat() [%s] OK\n", script_fileName );
|
||||
//
|
||||
pauseScriptThread( false ); // resume script thread
|
||||
//
|
||||
}
|
||||
|
||||
void ScriptEngine::set_onChat_handler( const char *funcName )
|
||||
{
|
||||
if( funcName == NULL ) // disable
|
||||
{
|
||||
m_onChat_enabled = false;
|
||||
m_onChat_functionName[0] = 0;
|
||||
return;
|
||||
}
|
||||
m_onChat_enabled = true;
|
||||
strncpy( m_onChat_functionName, funcName, sizeof(m_onChat_functionName)-1 );
|
||||
m_onChat_functionName[sizeof(m_onChat_functionName)-1] = 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user