Files
itgmania212121/stepmania/src/smlobby/smlobbyDlg.cpp
T
Chris Danford d698a5f1ec CString -> RString in RageUtil
ThemeMetric<CString> -> LocalizedString to eliminate dependencies
2005-12-20 08:35:47 +00:00

1064 lines
28 KiB
C++

// smlobbyDlg.cpp : implementation file
//
#include "stdafx.h"
#include "smlobby.h"
#include "smlobbyDlg.h"
#include "RageUtil.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "ConnectDlg.h"
#include "SendFileDialog.h"
#include <process.h>
/////////////////////////////////////////////////////////////////////////////
// global objects
static const NetworkInit g_wsInit;
static const unsigned short FILE_XFER_RATE = 4096;
irc::CIrcSession g_ircSession;
//irc::CIrcDCCServer g_DCCServer;
/////////////////////////////////////////////////////////////////////////////
// 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);
//We aren't trying to join any games just yet
m_bWantToJoin = false;
}
void CSmlobbyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSmlobbyDlg)
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);
DDX_Control(pDX, IDC_COMBO_MUSIC, m_comboMusic);
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)
ON_LBN_SELCHANGE(IDC_LIST_GAMES, OnSelchangeListGames)
ON_BN_CLICKED(IDC_BUTTON_BEGIN_GAME, OnButtonBeginGame)
ON_BN_CLICKED(IDC_REFRESH_GAME_LIST, OnRefreshGameList)
//}}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)
IRC_MAP_ENTRY(CSmlobbyDlg, "QUIT", OnIrc_QUIT)
IRC_MAP_ENTRY(CSmlobbyDlg, "PRIVMSG", OnIrc_PRIVMSG)
IRC_MAP_ENTRY(CSmlobbyDlg, "DCC", OnIrc_DCC_SEND)
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
IRC_MAP_ENTRY(CSmlobbyDlg, "376", OnIrc_RPL_ENDOFMOTD)
//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;
//
// 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 );
SortRStringArray( arrayGroupDirs );
//FILE *fp = fopen("SongHashes.txt","wt");
//int k=1000;
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 );
SortRStringArray( arraySongDirs );
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);
unsigned long ulSongHash = GetHashForDirectory( sSongDir );
m_comboMusic.AddString( sSongDir );
m_comboMusic.SetItemData( m_comboMusic.GetCount()-1, ulSongHash );
//fprintf(fp, "%d,%s,%lu\n", k, LPCSTR(sSongDir), ulSongHash);
//k++;
}
}
//fclose(fp);
//Make sure start game button is invisible
m_buttonStartGame.ShowWindow(FALSE);
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)
{
//See if were being sent a DCC comand
if (OnIrc_DCC_RECV(pmsg))
return true;
//see if someone is starting a game
if (OnIrc_DDR_GAME_START(pmsg))
return true;
UpdateChatMessages( pmsg );
return true;
}
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::
// PRIVMSG <recipient> :<0x01>SM START
//Make sure we have a parameter
if ( pmsg->parameters.size() < 1 )
return false;
//Make sure it's a SM start
if ( std::string::npos == pmsg->parameters[1].find("\001SM START") )
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;
}
bool CSmlobbyDlg::OnIrc_DCC_SEND(const CIrcMessage *pmsg)
{
//incoming:
// /DCC SEND <recipient>
//outgoing:
// PRIVMSG <recipient> :<0x01>DCC SEND <filename> <ipaddress> <port> <filesize> <0x01>
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
//irc::CIrcDCCServer::DCCTransferInfo dccInfo;
CSendFileDialog::DCCTransferInfo dccInfo;
dccInfo.m_bIsSender = true;
dccInfo.m_fileName = filename;
dccInfo.m_directory = dirname;
dccInfo.m_partnerName = partnerName;
dccInfo.m_uiPort = CSendFileDialog::MakePortReservation();
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
// make sure data is in network byte order
char szDCCString[512];
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 :\001DCC SEND %s %lu %u %lu \001",
dccInfo.m_partnerName, dccInfo.m_fileName, ip, port, filesize);
//Send of the dcc command to the other party
g_ircSession << irc::CIrcMessage(szDCCString);
//We now have enough info to open a window that will
//wait for the other party to connect to us and then
//transfer the file to them
//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;
return true;
}
bool CSmlobbyDlg::OnIrc_DCC_RECV(const CIrcMessage *pmsg)
{
//incoming::
// PRIVMSG <recipient> :<0x01>DCC SEND <filename> <ipaddress> <port> <filesize><0x01>
// filesize, ipaddress, and port are in network byte order
//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("\001DCC SEND") )
return false;
//Make sure we can read out the dcc send fields
const char* pszRawString = pmsg->parameters[1].c_str();
char szFilename[256];
unsigned long ulPartnerIP = 0L;
unsigned short uiPartnerPort = 0;
unsigned long ulFileSize = 0L;
//Snag the dcc info fields from the message string
int ret = sscanf(pszRawString, "\001DCC 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))
return false;
//Open a dialog box so user can decide where to save file
CString pathname = SelectFolder();
if (pathname.GetLength() <= 1)
return false;
//Assemble all of this info into a dcc info structure
//irc::CIrcDCCServer::DCCTransferInfo dccInfo;
CSendFileDialog::DCCTransferInfo dccInfo;
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;
//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;
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)
{
char szName[256];
//forget which chat room we joined
g_ircSession.GetInfo().sCurrentChatRoom = "";
//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();
//query the server for a list of chat rooms
g_ircSession << irc::CIrcMessage(CString("list"));
UpdateChatMessages( pmsg );
//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);
return true;
}
bool CSmlobbyDlg::OnIrc_KICK(const CIrcMessage* pmsg)
{
/*if( !pmsg->prefix.sNick.length() )
return false;
UpdateChatMessages( pmsg );*/
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;
}
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;
}
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>"
//topic format: "GameName serverIP ServerIRCName SongHash SongPath"
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
if (vecGameParams.size() != 5) return false;
//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());
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.\nWould you like me to send a message into that room asking\nsomeone 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;
}
}
}
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);
//Free any left over file transfer dialogs
CSendFileDialog::FreeAnyCompletedTransfers();
//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()
{
//make sure we're not in the room we are already trying to join
//Get the game name that was currently selected
char szGameName[128];
int nDummy;
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();
}
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;
}
//Make sure we have some songs
if(m_comboMusic.GetCount() <= 0)
{
MessageBox("You don't have any songs!");
return;
}
//Make sure a song is selected
int iIndex = m_comboMusic.GetCurSel();
if( iIndex == CB_ERR )
{
MessageBox("Need to select a song to play!");
return;
}
//Tell the server that we wanted to create a chat room
g_ircSession << irc::CIrcMessage(CString("join ") + "#" + gameName);
//Get the IP address of our machine in network byte order
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
CString sSongDir;
m_comboMusic.GetLBText( iIndex, sSongDir );
unsigned long hash = GetHashForDirectory( sSongDir );
//Now tell the server our game info
CString sIrcMessage = ssprintf( "topic #%s :%s %s %s %u ",
gameName,
gameName,
host_ip_str,
g_ircSession.GetInfo().sNick.c_str(),
hash );
//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
g_ircSession << irc::CIrcMessage(sIrcMessage);
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;
}
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;
}
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);
}
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 :\001DDR 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");
}