2002-12-02 05:44:00 +00:00
// smlobbyDlg.cpp : implementation file
//
#include "stdafx.h"
#include "smlobby.h"
#include "smlobbyDlg.h"
2002-12-03 07:20:41 +00:00
#include "RageUtil.h"
2002-12-02 05:44:00 +00:00
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE [] = __FILE__ ;
#endif
#include "ConnectDlg.h"
2002-12-19 23:59:12 +00:00
#include "SendFileDialog.h"
#include <process.h>
2002-12-02 05:44:00 +00:00
/////////////////////////////////////////////////////////////////////////////
// global objects
static const NetworkInit g_wsInit ;
static const unsigned short FILE_XFER_RATE = 4096 ;
irc :: CIrcSession g_ircSession ;
2002-12-19 23:59:12 +00:00
//irc::CIrcDCCServer g_DCCServer;
2002-12-02 05:44:00 +00:00
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public :
CAboutDlg ();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected :
virtual void DoDataExchange ( CDataExchange * pDX ); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected :
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP ()
};
CAboutDlg :: CAboutDlg () : CDialog ( CAboutDlg :: IDD )
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg :: DoDataExchange ( CDataExchange * pDX )
{
CDialog :: DoDataExchange ( pDX );
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP ( CAboutDlg , CDialog )
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()
/////////////////////////////////////////////////////////////////////////////
// CSmlobbyDlg dialog
CSmlobbyDlg :: CSmlobbyDlg ( CWnd * pParent /*=NULL*/ )
: CDialog ( CSmlobbyDlg :: IDD , pParent ), irc :: CIrcDefaultMonitor ( g_ircSession )
{
//{{AFX_DATA_INIT(CSmlobbyDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp () -> LoadIcon ( IDR_MAINFRAME );
2002-12-19 23:59:12 +00:00
//We aren't trying to join any games just yet
m_bWantToJoin = false ;
2002-12-02 05:44:00 +00:00
}
void CSmlobbyDlg :: DoDataExchange ( CDataExchange * pDX )
{
CDialog :: DoDataExchange ( pDX );
//{{AFX_DATA_MAP(CSmlobbyDlg)
2002-12-19 23:59:12 +00:00
DDX_Control ( pDX , IDC_BUTTON_BEGIN_GAME , m_buttonStartGame );
DDX_Control ( pDX , IDC_GAME_NAME_STATIC , m_staticGameName );
DDX_Control ( pDX , IDC_SELECT_MUSIC_STATIC , m_staticSelectMusic );
DDX_Control ( pDX , IDC_NEWGAMEFRAME , m_frameNewGame );
DDX_Control ( pDX , IDC_BUTTON_CREATE_GAME , m_buttonCreateGame );
2002-12-03 07:20:41 +00:00
DDX_Control ( pDX , IDC_COMBO_MUSIC , m_comboMusic );
2002-12-02 05:44:00 +00:00
DDX_Control ( pDX , IDC_EDIT_GAME_NAME , m_editGameName );
DDX_Control ( pDX , IDC_EDIT_GAME_INFO , m_editGameInfo );
DDX_Control ( pDX , IDC_LIST_USERS , m_listUsers );
DDX_Control ( pDX , IDC_EDIT_ENTRY , m_editEntry );
DDX_Control ( pDX , IDC_EDIT_CHAT_MESSAGES , m_editChatMessages );
DDX_Control ( pDX , IDC_LIST_GAMES , m_listGames );
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP ( CSmlobbyDlg , CDialog )
//{{AFX_MSG_MAP(CSmlobbyDlg)
ON_WM_SYSCOMMAND ()
ON_WM_QUERYDRAGICON ()
ON_WM_PAINT ()
ON_WM_DESTROY ()
ON_LBN_DBLCLK ( IDC_LIST_GAMES , OnDblclkListGames )
ON_BN_CLICKED ( IDC_BUTTON_CREATE_GAME , OnButtonCreateGame )
2002-12-19 23:59:12 +00:00
ON_LBN_SELCHANGE ( IDC_LIST_GAMES , OnSelchangeListGames )
ON_BN_CLICKED ( IDC_BUTTON_BEGIN_GAME , OnButtonBeginGame )
ON_BN_CLICKED ( IDC_REFRESH_GAME_LIST , OnRefreshGameList )
2002-12-02 05:44:00 +00:00
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()
/////////////////////////////////////////////////////////////////////////////
// CSmlobbyDlg message handlers
BOOL CSmlobbyDlg :: OnInitDialog ()
{
CDialog :: OnInitDialog ();
//Tell windows we have no default push button
SetDefID ( - 1 );
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT (( IDM_ABOUTBOX & 0xFFF0 ) == IDM_ABOUTBOX );
ASSERT ( IDM_ABOUTBOX < 0xF000 );
CMenu * pSysMenu = GetSystemMenu ( FALSE );
if ( pSysMenu != NULL )
{
CString strAboutMenu ;
strAboutMenu . LoadString ( IDS_ABOUTBOX );
if ( ! strAboutMenu . IsEmpty ())
{
pSysMenu -> AppendMenu ( MF_SEPARATOR );
pSysMenu -> AppendMenu ( MF_STRING , IDM_ABOUTBOX , strAboutMenu );
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon ( m_hIcon , TRUE ); // Set big icon
SetIcon ( m_hIcon , FALSE ); // Set small icon
//Add IRC reply call backs
IRC_MAP_ENTRY ( CSmlobbyDlg , "JOIN" , OnIrc_JOIN )
IRC_MAP_ENTRY ( CSmlobbyDlg , "KICK" , OnIrc_KICK )
IRC_MAP_ENTRY ( CSmlobbyDlg , "MODE" , OnIrc_MODE )
IRC_MAP_ENTRY ( CSmlobbyDlg , "NICK" , OnIrc_NICK )
IRC_MAP_ENTRY ( CSmlobbyDlg , "PART" , OnIrc_PART )
2002-12-19 23:59:12 +00:00
IRC_MAP_ENTRY ( CSmlobbyDlg , "QUIT" , OnIrc_QUIT )
2002-12-02 05:44:00 +00:00
IRC_MAP_ENTRY ( CSmlobbyDlg , "PRIVMSG" , OnIrc_PRIVMSG )
2002-12-08 19:40:18 +00:00
IRC_MAP_ENTRY ( CSmlobbyDlg , "DCC" , OnIrc_DCC_SEND )
2002-12-02 05:44:00 +00:00
IRC_MAP_ENTRY ( CSmlobbyDlg , "002" , OnIrc_YOURHOST )
IRC_MAP_ENTRY ( CSmlobbyDlg , "321" , OnIrc_RPL_LISTSTART )
IRC_MAP_ENTRY ( CSmlobbyDlg , "322" , OnIrc_RPL_LIST )
IRC_MAP_ENTRY ( CSmlobbyDlg , "323" , OnIrc_IgnoreMesg ) //RPL_LISTEND
IRC_MAP_ENTRY ( CSmlobbyDlg , "331" , OnIrc_IgnoreMesg ) //RPL_NOTOPIC
IRC_MAP_ENTRY ( CSmlobbyDlg , "332" , OnIrc_RPL_TOPIC )
IRC_MAP_ENTRY ( CSmlobbyDlg , "353" , OnIrc_RPL_NAMREPLY )
IRC_MAP_ENTRY ( CSmlobbyDlg , "366" , OnIrc_IgnoreMesg ) //RPL_ENDOFNAMES
2002-12-19 23:59:12 +00:00
IRC_MAP_ENTRY ( CSmlobbyDlg , "376" , OnIrc_RPL_ENDOFMOTD )
2002-12-02 05:44:00 +00:00
//Initialize IRC Server connection dialog
CConnectDlg dlg ;
dlg . m_sServer = _T ( "128.208.46.94" );
dlg . m_uiPort = 6667 ;
dlg . m_sNick = _T ( "smuser" );
dlg . m_sUserID = _T ( "vm" );
dlg . m_sFullName = _T ( "vm" );
if ( dlg . DoModal () != IDOK )
return TRUE ;
// set this document object as the session's monitor
g_ircSession . AddMonitor ( this );
CIrcSessionInfo si ;
si . sServer = dlg . m_sServer ;
si . iPort = dlg . m_uiPort ;
si . sNick = dlg . m_sNick ;
si . sUserID = dlg . m_sUserID ;
si . sFullName = dlg . m_sFullName ;
si . sPassword = dlg . m_sPassword ;
si . bIdentServer = true ;
si . iIdentServerPort = 113 ;
si . sIdentServerType = "UNIX" ;
si . sCurrentChatRoom = "" ;
bool m_bOk = g_ircSession . Connect ( si );
if ( ! m_bOk )
return FALSE ;
2002-12-03 07:20:41 +00:00
//
// populate drop-down list of songs
//
CString sDir = "Songs" ; // search only in "Songs" directory in program folder
// Find all group directories in "Songs" folder
CStringArray arrayGroupDirs ;
GetDirListing ( sDir + " \\ *.*" , arrayGroupDirs , true );
2005-12-20 08:35:47 +00:00
SortRStringArray ( arrayGroupDirs );
2002-12-03 07:20:41 +00:00
2002-12-19 23:59:12 +00:00
//FILE *fp = fopen("SongHashes.txt","wt");
//int k=1000;
2002-12-03 07:20:41 +00:00
for ( unsigned i = 0 ; i < arrayGroupDirs . GetSize (); i ++ ) // for each dir in /Songs/
{
CString sGroupDirName = arrayGroupDirs [ i ];
if ( 0 == stricmp ( sGroupDirName , "cvs" ) ) // the directory called "CVS"
continue ; // ignore it
// Find all Song folders in this group directory
CStringArray arraySongDirs ;
GetDirListing ( ssprintf ( "%s \\ %s \\ *.*" , sDir , sGroupDirName ), arraySongDirs , true );
2005-12-20 08:35:47 +00:00
SortRStringArray ( arraySongDirs );
2002-12-03 07:20:41 +00:00
for ( unsigned j = 0 ; j < arraySongDirs . GetSize (); j ++ ) // for each song dir
{
CString sSongDirName = arraySongDirs [ j ];
if ( 0 == stricmp ( sSongDirName , "cvs" ) ) // the directory called "CVS"
continue ; // ignore it
CString sSongDir = ssprintf ( "%s \\ %s \\ %s" , sDir , sGroupDirName , sSongDirName );
2002-12-19 23:59:12 +00:00
unsigned long ulSongHash = GetHashForDirectory ( sSongDir );
2002-12-03 07:20:41 +00:00
m_comboMusic . AddString ( sSongDir );
2002-12-19 23:59:12 +00:00
m_comboMusic . SetItemData ( m_comboMusic . GetCount () - 1 , ulSongHash );
//fprintf(fp, "%d,%s,%lu\n", k, LPCSTR(sSongDir), ulSongHash);
//k++;
2002-12-03 07:20:41 +00:00
}
}
2002-12-19 23:59:12 +00:00
//fclose(fp);
//Make sure start game button is invisible
m_buttonStartGame . ShowWindow ( FALSE );
2002-12-02 05:44:00 +00:00
return TRUE ; // return TRUE unless you set the focus to a control
}
void CSmlobbyDlg :: OnSysCommand ( UINT nID , LPARAM lParam )
{
if (( nID & 0xFFF0 ) == IDM_ABOUTBOX )
{
CAboutDlg dlgAbout ;
dlgAbout . DoModal ();
}
else
{
CDialog :: OnSysCommand ( nID , lParam );
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CSmlobbyDlg :: OnPaint ()
{
if ( IsIconic ())
{
CPaintDC dc ( this ); // device context for painting
SendMessage ( WM_ICONERASEBKGND , ( WPARAM ) dc . GetSafeHdc (), 0 );
// Center icon in client rectangle
int cxIcon = GetSystemMetrics ( SM_CXICON );
int cyIcon = GetSystemMetrics ( SM_CYICON );
CRect rect ;
GetClientRect ( & rect );
int x = ( rect . Width () - cxIcon + 1 ) / 2 ;
int y = ( rect . Height () - cyIcon + 1 ) / 2 ;
// Draw the icon
dc . DrawIcon ( x , y , m_hIcon );
}
else
{
CDialog :: OnPaint ();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSmlobbyDlg :: OnQueryDragIcon ()
{
return ( HCURSOR ) m_hIcon ;
}
bool CSmlobbyDlg :: OnIrc_YOURHOST ( const CIrcMessage * pmsg )
{
CIrcDefaultMonitor :: OnIrc_YOURHOST ( pmsg );
//query the server for a list of chat rooms
g_ircSession << irc :: CIrcMessage ( CString ( "list" ));
return false ;
}
bool CSmlobbyDlg :: OnIrc_NICK ( const CIrcMessage * pmsg )
{
CIrcDefaultMonitor :: OnIrc_NICK ( pmsg );
if ( pmsg -> prefix . sNick == m_session . GetInfo (). sNick && ( pmsg -> parameters . size () > 0 ) )
{
}
return false ;
}
bool CSmlobbyDlg :: OnIrc_PRIVMSG ( const CIrcMessage * pmsg )
{
2002-12-19 23:59:12 +00:00
//See if were being sent a DCC comand
2002-12-03 03:19:51 +00:00
if ( OnIrc_DCC_RECV ( pmsg ))
return true ;
2002-12-19 23:59:12 +00:00
//see if someone is starting a game
if ( OnIrc_DDR_GAME_START ( pmsg ))
return true ;
2002-12-02 05:44:00 +00:00
UpdateChatMessages ( pmsg );
return true ;
}
2002-12-19 23:59:12 +00:00
bool CSmlobbyDlg :: OnIrc_RPL_ENDOFMOTD ( const CIrcMessage * pmsg )
{
g_ircSession << irc :: CIrcMessage ( CString ( "join #mainlobby" ));
return true ;
}
bool CSmlobbyDlg :: OnIrc_DDR_GAME_START ( const CIrcMessage * pmsg )
{
//incoming::
2005-10-07 05:00:52 +00:00
// PRIVMSG <recipient> :<0x01>SM START
2002-12-19 23:59:12 +00:00
//Make sure we have a parameter
if ( pmsg -> parameters . size () < 1 )
return false ;
2005-10-07 05:00:52 +00:00
//Make sure it's a SM start
if ( std :: string :: npos == pmsg -> parameters [ 1 ]. find ( " \001 SM START" ) )
2002-12-19 23:59:12 +00:00
return false ;
//Get the info for this chat room
String sSongPath = g_ircSession . GetInfo (). sSongPath ;
String sIP = g_ircSession . GetInfo (). sHostIP ;
String sMyUserName = g_ircSession . GetInfo (). sNick ;
//Are we the one who stated the game
if ( m_buttonStartGame . IsWindowVisible () == TRUE )
{
m_buttonStartGame . ShowWindow ( FALSE );
if ( ! WinExec ( "smserver.exe" ) )
AfxMessageBox ( "Lobby unable to start Stepmania game server!" );
}
//Start up the game
if ( ! WinExec ( "stepmania.exe " + sSongPath + " " + sIP . c_str () + " " + sMyUserName . c_str ()) )
AfxMessageBox ( "Lobby unable to start Stepmania!" );
//Bail from this lobby
g_ircSession << irc :: CIrcMessage ( CString ( "part " ) + CString ( g_ircSession . GetInfo (). sCurrentChatRoom . c_str ()));
return true ;
}
2002-12-08 19:40:18 +00:00
bool CSmlobbyDlg :: OnIrc_DCC_SEND ( const CIrcMessage * pmsg )
{
//incoming:
// /DCC SEND <recipient>
//outgoing:
2002-12-19 23:59:12 +00:00
// PRIVMSG <recipient> :<0x01>DCC SEND <filename> <ipaddress> <port> <filesize> <0x01>
2002-12-08 19:40:18 +00:00
const kRecptParm = 1 ;
//Make sure we have a parameter
if ( pmsg -> parameters . size () < ( kRecptParm + 1 ) )
return false ;
//Make sure we're not trying to send a file to ourselves (people can be silly :p)
CString partnerName = pmsg -> parameters [ kRecptParm ]. c_str ();
if ( partnerName == g_ircSession . GetInfo (). sNick . c_str ())
return false ;
//Make sure partner is currently in the room
if ( LB_ERR == m_listUsers . FindString ( - 1 , partnerName ))
return false ;
//open a file dialog box to get the file the user wants to send
CFileDialog fileDialog ( TRUE , NULL , NULL , OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER ,
NULL , AfxGetMainWnd ());
if ( IDOK != fileDialog . DoModal ())
return false ;
//Setup retrieval params
IPaddress ipaddr ;
char szHostName [ 256 ];
gethostname ( szHostName , 256 );
SDLNet_ResolveHost ( & ipaddr , szHostName , 0 );
//Get filename and directory
CString filename = fileDialog . GetFileName ();
CString fullpath = fileDialog . GetPathName ();
CString dirname = fullpath . Left ( fullpath . GetLength () - filename . GetLength ());
//Place all of the connection info into a dcc info structure
2002-12-19 23:59:12 +00:00
//irc::CIrcDCCServer::DCCTransferInfo dccInfo;
CSendFileDialog :: DCCTransferInfo dccInfo ;
2002-12-08 19:40:18 +00:00
dccInfo . m_bIsSender = true ;
dccInfo . m_fileName = filename ;
dccInfo . m_directory = dirname ;
dccInfo . m_partnerName = partnerName ;
2002-12-19 23:59:12 +00:00
dccInfo . m_uiPort = CSendFileDialog :: MakePortReservation ();
2002-12-08 19:40:18 +00:00
dccInfo . m_uiXferRate = FILE_XFER_RATE ;
dccInfo . m_ulFileSize = GetFileSizeInBytes ( fullpath );
dccInfo . m_ulPartnerIP = ipaddr . host ;
//Create a dcc command to send to the user to which our file is going
2002-12-19 23:59:12 +00:00
// make sure data is in network byte order
2002-12-08 19:40:18 +00:00
char szDCCString [ 512 ];
2002-12-19 23:59:12 +00:00
unsigned long ip = ntohl ( ipaddr . host );
unsigned short port = dccInfo . m_uiPort ; //htons(dccInfo.m_uiPort);
unsigned long filesize = dccInfo . m_ulFileSize ; //htonl(dccInfo.m_ulFileSize);
sprintf ( szDCCString , "PRIVMSG %s : \001 DCC SEND %s %lu %u %lu \001 " ,
dccInfo . m_partnerName , dccInfo . m_fileName , ip , port , filesize );
2002-12-08 19:40:18 +00:00
//Send of the dcc command to the other party
g_ircSession << irc :: CIrcMessage ( szDCCString );
2002-12-19 23:59:12 +00:00
//We now have enough info to open a window that will
2002-12-08 19:40:18 +00:00
//wait for the other party to connect to us and then
//transfer the file to them
2002-12-19 23:59:12 +00:00
//g_DCCServer.Start(dccInfo);
CSendFileDialog * dlg = new CSendFileDialog ( dccInfo );
//Remember this dialog so that when we exit the app
//CSendFileDialog::FreeAnyCompletedTransfers() can release it
CSendFileDialog :: AddTransferDialog ( dlg );
//Now let's try and open the window
if ( ! dlg -> Create ( IDD_FILEXFER , NULL ) || ! dlg -> Setup () ) return false ;
2002-12-08 19:40:18 +00:00
return true ;
}
2002-12-02 05:44:00 +00:00
bool CSmlobbyDlg :: OnIrc_DCC_RECV ( const CIrcMessage * pmsg )
{
2002-12-08 19:40:18 +00:00
//incoming::
// PRIVMSG <recipient> :<0x01>DCC SEND <filename> <ipaddress> <port> <filesize><0x01>
2002-12-19 23:59:12 +00:00
// filesize, ipaddress, and port are in network byte order
2002-12-08 19:40:18 +00:00
2002-12-02 05:44:00 +00:00
//Make sure we have a parameter
if ( pmsg -> parameters . size () < 1 )
return false ;
//Make sure it's a DCC send
if ( std :: string :: npos == pmsg -> parameters [ 1 ]. find ( " \001 DCC SEND" ) )
return false ;
//Make sure we can read out the dcc send fields
const char * pszRawString = pmsg -> parameters [ 1 ]. c_str ();
char szFilename [ 256 ];
2002-12-19 23:59:12 +00:00
unsigned long ulPartnerIP = 0L ;
unsigned short uiPartnerPort = 0 ;
unsigned long ulFileSize = 0L ;
2002-12-02 05:44:00 +00:00
2002-12-08 19:40:18 +00:00
//Snag the dcc info fields from the message string
2002-12-19 23:59:12 +00:00
int ret = sscanf ( pszRawString , " \001 DCC SEND %255s %lu %u %lu \001 " ,
& szFilename , & ulPartnerIP , & uiPartnerPort , & ulFileSize );
if ( 4 != ret )
return false ;
//Transform data from network byte order to host byte order
//ulFileSize = ntohl(ulFileSize);
//uiPartnerPort = ntohs(uiPartnerPort);
//ulPartnerIP = ntohl(ulPartnerIP);
//See if this is an echo of a connection I already sent
IPaddress ipaddr ;
char szHostName [ 256 ];
gethostname ( szHostName , 256 );
SDLNet_ResolveHost ( & ipaddr , szHostName , 0 );
if ( ulPartnerIP == ntohl ( ipaddr . host ))
2002-12-02 05:44:00 +00:00
return false ;
//Open a dialog box so user can decide where to save file
2002-12-03 03:19:51 +00:00
CString pathname = SelectFolder ();
2002-12-08 19:40:18 +00:00
if ( pathname . GetLength () <= 1 )
return false ;
2002-12-02 05:44:00 +00:00
2002-12-08 19:40:18 +00:00
//Assemble all of this info into a dcc info structure
2002-12-19 23:59:12 +00:00
//irc::CIrcDCCServer::DCCTransferInfo dccInfo;
CSendFileDialog :: DCCTransferInfo dccInfo ;
2002-12-08 19:40:18 +00:00
dccInfo . m_bIsSender = false ;
dccInfo . m_directory = pathname ;
dccInfo . m_fileName = szFilename ;
dccInfo . m_partnerName = pmsg -> prefix . sNick . c_str ();
dccInfo . m_uiPort = uiPartnerPort ;
dccInfo . m_uiXferRate = FILE_XFER_RATE ;
dccInfo . m_ulFileSize = ulFileSize ;
dccInfo . m_ulPartnerIP = ulPartnerIP ;
2002-12-02 05:44:00 +00:00
2002-12-19 23:59:12 +00:00
//We now have enough info to create a window to deal with file xfer
//g_DCCServer.Start(dccInfo);
CSendFileDialog * dlg = new CSendFileDialog ( dccInfo );
//Remember this dialog so that when we exit the app
//CSendFileDialog::FreeAnyCompletedTransfers() can release it
CSendFileDialog :: AddTransferDialog ( dlg );
//Now let's try and open the window
if ( ! dlg -> Create ( IDD_FILEXFER , NULL ) || ! dlg -> Setup () ) return false ;
2002-12-02 05:44:00 +00:00
return true ;
}
bool CSmlobbyDlg :: OnIrc_JOIN ( const CIrcMessage * pmsg )
{
//Put update on message window
UpdateChatMessages ( pmsg );
//Remember which chat room we joined
String chatRoomName ( pmsg -> parameters [ 0 ]. c_str ());
g_ircSession . GetInfo (). sCurrentChatRoom = chatRoomName ;
//query the server for a list of names in this room
g_ircSession << irc :: CIrcMessage ( CString ( "names " ) + CString ( chatRoomName . c_str ()));
//query the server for a list of rooms (could have changed)
g_ircSession << irc :: CIrcMessage ( CString ( "list" ));
return true ;
}
bool CSmlobbyDlg :: OnIrc_PART ( const CIrcMessage * pmsg )
{
2002-12-19 23:59:12 +00:00
char szName [ 256 ];
2002-12-02 05:44:00 +00:00
//forget which chat room we joined
g_ircSession . GetInfo (). sCurrentChatRoom = "" ;
2002-12-19 23:59:12 +00:00
//if we are the host kick everyone else out
if ( g_ircSession . GetInfo (). bIsGameHost )
{
for ( int i = 0 ; i < m_listUsers . GetCount (); i ++ )
{
m_listUsers . GetDlgItemText ( i , szName , 256 );
if ( szName [ 0 ] != '@' )
{
}
}
}
//make sure to reset the names lists since were leaving current room
m_listUsers . ResetContent ();
2002-12-02 05:44:00 +00:00
//query the server for a list of chat rooms
g_ircSession << irc :: CIrcMessage ( CString ( "list" ));
UpdateChatMessages ( pmsg );
2002-12-19 23:59:12 +00:00
//Now that we've left a game, we can allow user to create a game
m_frameNewGame . ShowWindow ( TRUE );
m_buttonCreateGame . ShowWindow ( TRUE );
m_comboMusic . ShowWindow ( TRUE );
m_editGameName . ShowWindow ( TRUE );
m_staticGameName . ShowWindow ( TRUE );
m_staticSelectMusic . ShowWindow ( TRUE );
2002-12-02 05:44:00 +00:00
return true ;
}
bool CSmlobbyDlg :: OnIrc_KICK ( const CIrcMessage * pmsg )
{
2002-12-19 23:59:12 +00:00
/*if( !pmsg->prefix.sNick.length() )
2002-12-02 05:44:00 +00:00
return false;
2002-12-19 23:59:12 +00:00
UpdateChatMessages( pmsg );*/
2002-12-02 05:44:00 +00:00
return true ;
}
bool CSmlobbyDlg :: OnIrc_MODE ( const CIrcMessage * pmsg )
{
if ( ! pmsg -> prefix . sNick . length () )
return false ;
if ( pmsg -> prefix . sNick == m_session . GetInfo (). sNick )
return false ;
UpdateChatMessages ( pmsg );
return true ;
}
2002-12-19 23:59:12 +00:00
bool CSmlobbyDlg :: OnIrc_QUIT ( const CIrcMessage * pmsg )
{
//leave a game if we are currently in one
if ( g_ircSession . GetInfo (). sCurrentChatRoom != "" )
{
g_ircSession << irc :: CIrcMessage ( CString ( "part " ) + CString ( g_ircSession . GetInfo (). sCurrentChatRoom . c_str ()));
}
PostQuitMessage ( 0 );
return true ;
}
2002-12-02 05:44:00 +00:00
bool CSmlobbyDlg :: OnIrc_RPL_LISTSTART ( const CIrcMessage * pmsg )
{
//Were going to be getting a new list of rooms
//so clear out the old ones
m_listGames . ResetContent ();
return true ;
}
bool CSmlobbyDlg :: OnIrc_RPL_LIST ( const CIrcMessage * pmsg )
{
//Add the current game to the list
//msg Format: "<channel> <# visible> :<topic>"
String name = pmsg -> parameters [ 1 ] + " (" + pmsg -> parameters [ 2 ] + ")" ;
m_listGames . AddString ( name . c_str ());
return true ;
}
bool CSmlobbyDlg :: OnIrc_RPL_TOPIC ( const CIrcMessage * pmsg )
{
//Clean out the game info box
m_editGameInfo . SetSel ( 0 , - 1 );
m_editGameInfo . Clear ();
//Put the info for a game up in the game info box
//msg Format: "<channel> :<topic>"
2002-12-19 23:59:12 +00:00
//topic format: "GameName serverIP ServerIRCName SongHash SongPath"
2002-12-02 05:44:00 +00:00
std :: vector < String > vecGameParams ;
const char * p1 = pmsg -> parameters [ 2 ]. c_str ();
const char * p2 = p1 ;
//Extract all of the topic params
while ( * p1 )
{
// seek end of name
while ( * p2 && * p2 != ' ' ) p2 ++ ;
//add name to the list
vecGameParams . push_back ( String ( p1 , p2 - p1 ));
// eat white space
while ( * p2 && * p2 == ' ' ) p2 ++ ;
p1 = p2 ;
}
//somehow we lost some game info
2002-12-19 23:59:12 +00:00
if ( vecGameParams . size () != 5 ) return false ;
2002-12-02 05:44:00 +00:00
//Display game info
m_editGameInfo . SetSel ( - 1 , 0 );
m_editGameInfo . ReplaceSel (( "Game Name: " + vecGameParams [ 0 ] + " \n " ). c_str ());
m_editGameInfo . ReplaceSel (( "Server IP: " + vecGameParams [ 1 ] + " \n " ). c_str ());
m_editGameInfo . ReplaceSel (( "Host IRC Name: " + vecGameParams [ 2 ] + " \n " ). c_str ());
2002-12-19 23:59:12 +00:00
m_editGameInfo . ReplaceSel (( "Song: " + vecGameParams [ 4 ] + " \n " ). c_str ());
//Get the hash value
unsigned long hash ;
sscanf ( vecGameParams [ 3 ]. c_str (), "%ul" , & hash );
//Remember the game info for later
g_ircSession . SetGameInfo (( m_buttonStartGame . IsWindowVisible () == TRUE ) ? true : false ,
vecGameParams [ 4 ], hash , vecGameParams [ 2 ], vecGameParams [ 1 ]);
//See if we wanted to join a game
if ( m_bWantToJoin == true )
{
m_bWantToJoin = false ;
//See if we have a song that matches that hash
if ( FindSongNameFromHash ( hash ) >= 0 )
{
//Tell the server that we join this a chat room
g_ircSession << irc :: CIrcMessage ( CString ( "join #" ) +
CString ( vecGameParams [ 0 ]. c_str ()));
return true ;
}
//Otherwise ask if we want to send a song download request
else
{
int ret = AfxMessageBox ( "I'm sorry, you don't have the song their using. \n Would you like me to send a message into that room asking \n someone to send you a copy so that you can join?" , MB_YESNO );
if ( ret == IDYES )
{
String msg ;
msg = "PRIVMSG #" + vecGameParams [ 0 ] + " "
+ g_ircSession . GetInfo (). sNick
+ " would like to join you, but they need a copy of "
+ vecGameParams [ 4 ];
g_ircSession << irc :: CIrcMessage ( CString ( msg . c_str ()));
return false ;
}
}
}
2002-12-02 05:44:00 +00:00
return true ;
}
bool CSmlobbyDlg :: OnIrc_RPL_NAMREPLY ( const CIrcMessage * pmsg )
{
//Reset the names list
m_listUsers . ResetContent ();
//now dump all of the users into the user list
//msg format: "<channel> :[[@|+]<nick> [[@|+]<nick> [...]]]"
const char * p1 = pmsg -> parameters [ 3 ]. c_str ();
const char * p2 = p1 ;
//keep trying to read off names while the list isn't null
while ( * p1 )
{
// seek end of name
while ( * p2 && ! isspace ( * p2 ) ) p2 ++ ;
//add name to the list
m_listUsers . AddString ( String ( p1 , p2 - p1 ). c_str ());
// eat white space
while ( * p2 && isspace ( * p2 ) ) p2 ++ ;
p1 = p2 ;
}
return true ;
}
void CSmlobbyDlg :: OnIrcDefault ( const CIrcMessage * pmsg )
{
CIrcDefaultMonitor :: OnIrcDefault ( pmsg );
if ( pmsg && m_session . GetInfo (). sServerName . length () )
{
UpdateChatMessages ( pmsg );
}
}
void CSmlobbyDlg :: OnIrcDisconnected ()
{
AfxGetMainWnd () -> PostMessage ( WM_COMMAND , ID_FILE_CLOSE );
}
void CSmlobbyDlg :: OnDestroy ()
{
CDialog :: OnDestroy ();
g_ircSession . Disconnect ();
g_ircSession . RemoveMonitor ( this );
2002-12-19 23:59:12 +00:00
//Free any left over file transfer dialogs
CSendFileDialog :: FreeAnyCompletedTransfers ();
2002-12-02 05:44:00 +00:00
//Close the parent application
AfxGetApp () -> ExitInstance ();
}
void CSmlobbyDlg :: UpdateChatMessages ( const CIrcMessage * p )
{
if ( p )
{
m_editChatMessages . SetSel ( - 1 , 0 );
m_editChatMessages . SendMessage ( EM_SCROLLCARET );
#ifdef _DEBUG
m_editChatMessages . ReplaceSel (( p -> sCommand + " " ). c_str ());
#endif
if ( p -> sCommand == "NOTICE" )
{
String param = p -> parameters [ 1 ];
const char * c_param = param . c_str ();
p = p ;
}
if ( p -> prefix . sNick . length () )
{
m_editChatMessages . ReplaceSel (( "<" + p -> prefix . sNick + "> " ). c_str ());
}
for ( int i = 1 ; i < p -> parameters . size (); i ++ )
{
m_editChatMessages . ReplaceSel (( p -> parameters [ i ] + " " ). c_str ());
}
m_editChatMessages . ReplaceSel ( " \r\n " );
}
}
void CSmlobbyDlg :: OnDblclkListGames ()
{
2002-12-19 23:59:12 +00:00
//make sure we're not in the room we are already trying to join
2002-12-02 05:44:00 +00:00
//Get the game name that was currently selected
2002-12-19 23:59:12 +00:00
char szGameName [ 128 ];
int nDummy ;
2002-12-02 05:44:00 +00:00
2002-12-19 23:59:12 +00:00
int nIndex = m_listGames . GetCurSel ();
if ( nIndex == LB_ERR ) return ;
m_listGames . GetText ( nIndex , szGameName );
sscanf ( szGameName , "%s (%d)" , & szGameName , & nDummy );
if ( g_ircSession . GetInfo (). sCurrentChatRoom == szGameName ) return ;
//other wise, tell server we want to part this channel
if ( g_ircSession . GetInfo (). sCurrentChatRoom != "" )
g_ircSession << irc :: CIrcMessage ( CString ( "part " ) + CString ( szGameName ));
m_bWantToJoin = true ;
OnSelchangeListGames ();
2002-12-02 05:44:00 +00:00
}
void CSmlobbyDlg :: OnSelchangeListGames ()
{
//Get the game name that was currently selected
int nIndex = m_listGames . GetCurSel ();
char szGameName [ 128 ];
int nDummy ;
if ( nIndex != LB_ERR )
{
m_listGames . GetText ( nIndex , szGameName );
sscanf ( szGameName , "%s (%d)" , & szGameName , & nDummy );
//Tell the server that we wanted to join a chat room
g_ircSession << irc :: CIrcMessage ( CString ( "topic " ) + CString ( szGameName ));
}
}
void CSmlobbyDlg :: OnButtonCreateGame ()
{
//Strip all non alphanumeric characters from the name
// so irc will be ok with it as a chat room name
CString gameName ;
char szRawGameName [ 256 ];
m_editGameName . GetLine ( 0 , szRawGameName , 255 );
for ( int i = 0 ; i < strlen ( szRawGameName ); i ++ )
{
if ( isalnum ( szRawGameName [ i ]) )
gameName += szRawGameName [ i ];
}
//Make sure user has given us a game name
if ( gameName . GetLength () <= 0 )
{
MessageBox ( "You need some letters or numbers in your name!" );
return ;
}
//Make sure no one else has this name
if ( ! IsUniqueGameName ( gameName ))
{
MessageBox ( "Game already exists with that name!" );
return ;
}
2002-12-19 23:59:12 +00:00
//Make sure we have some songs
if ( m_comboMusic . GetCount () <= 0 )
{
MessageBox ( "You don't have any songs!" );
return ;
}
2002-12-08 19:40:18 +00:00
//Make sure a song is selected
int iIndex = m_comboMusic . GetCurSel ();
2002-12-19 23:59:12 +00:00
if ( iIndex == CB_ERR )
2002-12-08 19:40:18 +00:00
{
MessageBox ( "Need to select a song to play!" );
return ;
}
2002-12-02 05:44:00 +00:00
//Tell the server that we wanted to create a chat room
g_ircSession << irc :: CIrcMessage ( CString ( "join " ) + "#" + gameName );
2002-12-08 19:40:18 +00:00
//Get the IP address of our machine in network byte order
2002-12-02 05:44:00 +00:00
IPaddress ipaddr ;
char szHostName [ 256 ];
gethostname ( szHostName , 256 );
SDLNet_ResolveHost ( & ipaddr , szHostName , 0 );
unsigned char * ip = ( unsigned char * ) & ( ipaddr . host );
char host_ip_str [ 20 ];
sprintf ( host_ip_str , "%d.%d.%d.%d" , ip [ 0 ], ip [ 1 ], ip [ 2 ], ip [ 3 ]);
//Insert song name/hash code here
2002-12-03 07:20:41 +00:00
CString sSongDir ;
m_comboMusic . GetLBText ( iIndex , sSongDir );
unsigned long hash = GetHashForDirectory ( sSongDir );
2002-12-02 05:44:00 +00:00
//Now tell the server our game info
2002-12-19 23:59:12 +00:00
CString sIrcMessage = ssprintf ( "topic #%s :%s %s %s %u " ,
2002-12-03 07:20:41 +00:00
gameName ,
gameName ,
host_ip_str ,
g_ircSession . GetInfo (). sNick . c_str (),
hash );
2002-12-19 23:59:12 +00:00
//Tack on the song name
sIrcMessage += sSongDir ;
//make sure to clean out the values you put in the fields
m_comboMusic . SetCurSel ( - 1 );
m_editGameName . SetSel ( 0 , - 1 );
m_editGameName . Clear ();
//Make sure we can't create another game until we part this lobby
m_frameNewGame . ShowWindow ( FALSE );
m_buttonCreateGame . ShowWindow ( FALSE );
m_comboMusic . ShowWindow ( FALSE );
m_editGameName . ShowWindow ( FALSE );
m_staticGameName . ShowWindow ( FALSE );
m_staticSelectMusic . ShowWindow ( FALSE );
//Show the start game button
m_buttonStartGame . ShowWindow ( TRUE );
//Send off topic and request update now
2002-12-03 07:20:41 +00:00
g_ircSession << irc :: CIrcMessage ( sIrcMessage );
2002-12-19 23:59:12 +00:00
g_ircSession << irc :: CIrcMessage ( CString ( "topic #" ) + gameName );
}
int CSmlobbyDlg :: FindSongNameFromHash ( unsigned long hash )
{
unsigned long comboHash ;
for ( int i = 0 ; i < m_comboMusic . GetCount (); i ++ )
{
comboHash = m_comboMusic . GetItemData ( i );
if ( hash == comboHash )
return i ;
}
return - 1 ;
2002-12-02 05:44:00 +00:00
}
bool CSmlobbyDlg :: IsUniqueGameName ( const CString GameName )
{
CString aName ;
//Search list of games to make sure ours is unique
for ( int i = 0 ; i < m_listGames . GetCount (); i ++ )
{
m_listGames . GetText ( i , aName );
if ( aName == GameName )
return false ;
}
return true ;
}
2002-12-03 03:19:51 +00:00
CString CSmlobbyDlg :: SelectFolder ()
{
char szTitle [] = "Select a Folder" ;
char szDisplayName [ MAX_PATH ] = "" ;
char szPath [ MAX_PATH ] = "" ;
BROWSEINFO bi ;
szPath [ 0 ] = '\0' ;
bi . hwndOwner = m_hWnd ; // Handle of the owner window
bi . pidlRoot = NULL ; // Desktop folder is used
bi . lpszTitle = szTitle ; // Title of the dialog box
bi . pszDisplayName = szDisplayName ; // Buffer for selected folder name
bi . ulFlags = BIF_RETURNONLYFSDIRS ; // Only returns file system directories
bi . lpfn = NULL ;
bi . lParam = 0 ;
LPITEMIDLIST pItemIDList = SHBrowseForFolder ( & bi );
if ( pItemIDList ) {
if ( SHGetPathFromIDList ( pItemIDList , szPath )) {
SetWindowText ( szPath );
}
// Avoid memory leaks by deleting the PIDL using the shell's task allocator
IMalloc * pMalloc ;
if ( SHGetMalloc ( & pMalloc ) != NOERROR ) {
TRACE ( "Failed to get pointer to shells task allocator" );
return CString ( szPath );
}
pMalloc -> Free ( pItemIDList );
if ( pMalloc )
pMalloc -> Release ();
}
return CString ( szPath );
2002-12-03 07:20:41 +00:00
}
2002-12-19 23:59:12 +00:00
void CSmlobbyDlg :: OnButtonBeginGame ()
{
//Create a dcc command to send to the user to which our file is going
char szString [ 64 ];
sprintf ( szString , "PRIVMSG %s : \001 DDR START" , g_ircSession . GetInfo (). sCurrentChatRoom . c_str ());
//Send of the dcc command to the other party
g_ircSession << irc :: CIrcMessage ( szString );
}
bool CSmlobbyDlg :: WinExec ( String sCmdLine )
{
STARTUPINFO si ;
PROCESS_INFORMATION pi ;
memset ( & si , 0 , sizeof ( si ));
memset ( & pi , 0 , sizeof ( pi ));
si . cb = sizeof ( si );
si . wShowWindow = SW_SHOW ;
char szCmdLine [ 256 ];
strncpy ( szCmdLine , sCmdLine . c_str (), 255 );
int ret = CreateProcess (
NULL , // pointer to name of executable module
szCmdLine , // pointer to command line string
NULL , // pointer to process security attributes
NULL , // pointer to thread security attributes
FALSE , // handle inheritance flag
NULL , // creation flags
NULL , // pointer to new environment block
NULL , // pointer to current directory name
& si , // pointer to STARTUPINFO
& pi // pointer to PROCESS_INFORMATION
);
if ( FAILED ( ret )) return false ;
else return true ;
}
void CSmlobbyDlg :: OnRefreshGameList ()
{
//Ask for a refresh of the games
g_ircSession << irc :: CIrcMessage ( "list" );
}