mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
497 lines
13 KiB
C++
497 lines
13 KiB
C++
// sbmfcsampleDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "sbmfcsample.h"
|
|
#include "sbmfcsampleDlg.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
//SB - timer ID and frequency
|
|
#define TIMER_ID 100
|
|
#define TIMER_FREQUENCY 10
|
|
|
|
//SB - server list columns
|
|
#define COL_SERVERNAME 0
|
|
#define COL_PING 1
|
|
#define COL_PLAYERS 2
|
|
#define COL_MAPNAME 3
|
|
#define COL_GAMETYPE 4
|
|
|
|
//SB - player list columns
|
|
#define COL_PNAME 0
|
|
#define COL_PPING 1
|
|
#define COL_PSCORE 2
|
|
|
|
// 11-02-2004 : Saad Nader
|
|
// replaced with a GUI-based way of doing it.
|
|
//SB - starting and ending port for LAN game searches
|
|
//#define START_PORT 7778
|
|
//#define END_PORT (START_PORT + 100)
|
|
|
|
//SB - maximum number of concurrent updates
|
|
#define MAX_UPDATES 30
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSbmfcsampleDlg dialog
|
|
|
|
CSbmfcsampleDlg::CSbmfcsampleDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CSbmfcsampleDlg::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CSbmfcsampleDlg)
|
|
m_filter = _T("");
|
|
m_gamename = _T("");
|
|
m_startPort = 0;
|
|
m_endPort = 0;
|
|
//}}AFX_DATA_INIT
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CSbmfcsampleDlg)
|
|
DDX_Control(pDX, IDC_SERVERS, m_servers);
|
|
DDX_Control(pDX, IDC_PROGRESS, m_progress);
|
|
DDX_Control(pDX, IDC_SERVERLIST, m_serverList);
|
|
DDX_Control(pDX, IDC_PLAYERLIST, m_playerList);
|
|
DDX_Text(pDX, IDC_FILTER, m_filter);
|
|
DDX_Text(pDX, IDC_GAMENAME, m_gamename);
|
|
DDX_Text(pDX, IDC_STARTP, m_startPort);
|
|
DDX_Text(pDX, IDC_ENDP, m_endPort);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CSbmfcsampleDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CSbmfcsampleDlg)
|
|
ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
|
|
ON_NOTIFY(NM_CLICK, IDC_SERVERLIST, OnClickServerlist)
|
|
ON_NOTIFY(NM_DBLCLK, IDC_SERVERLIST, OnDblclkServerlist)
|
|
ON_WM_TIMER()
|
|
ON_WM_PAINT()
|
|
ON_WM_QUERYDRAGICON()
|
|
ON_NOTIFY(LVN_COLUMNCLICK, IDC_SERVERLIST, OnColumnclickServerlist)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSbmfcsampleDlg message handlers
|
|
|
|
BOOL CSbmfcsampleDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
SetIcon(m_hIcon, TRUE);
|
|
SetIcon(m_hIcon, FALSE);
|
|
|
|
//SB - setup list columns
|
|
m_serverList.InsertColumn(COL_SERVERNAME, "Server Name", LVCFMT_LEFT, 150, -1);
|
|
m_serverList.InsertColumn(COL_PING, "Ping", LVCFMT_LEFT, 50, 0);
|
|
m_serverList.InsertColumn(COL_PLAYERS, "Players", LVCFMT_LEFT, 75, 1);
|
|
m_serverList.InsertColumn(COL_MAPNAME, "Map", LVCFMT_LEFT, 75, 2);
|
|
m_serverList.InsertColumn(COL_GAMETYPE, "GameType", LVCFMT_LEFT, 100, 3);
|
|
m_playerList.InsertColumn(COL_PNAME, "Player Name", LVCFMT_LEFT, 150, -1);
|
|
m_playerList.InsertColumn(COL_PPING, "Ping", LVCFMT_LEFT, 50, 0);
|
|
m_playerList.InsertColumn(COL_PSCORE, "Score", LVCFMT_LEFT, 50, 1);
|
|
ListView_SetExtendedListViewStyle(m_serverList.m_hWnd, LVS_EX_FULLROWSELECT);
|
|
ListView_SetExtendedListViewStyle(m_playerList.m_hWnd, LVS_EX_FULLROWSELECT);
|
|
|
|
//SB - default to Internet
|
|
CheckRadioButton(IDC_INTERNET, IDC_LAN, IDC_INTERNET);
|
|
|
|
//SB - default to QR2
|
|
CheckRadioButton(IDC_GOA, IDC_QR2, IDC_QR2);
|
|
|
|
//SB - no server browser yet
|
|
m_serverBrowser = NULL;
|
|
|
|
//SB - no timer yet
|
|
m_timerID = 0;
|
|
|
|
//SB - no servers yet
|
|
m_servers.SetWindowText("");
|
|
|
|
//SB - check that the game's backend is available
|
|
GSIACResult result;
|
|
GSIStartAvailableCheck("gmtest");
|
|
while((result = GSIAvailableCheckThink()) == GSIACWaiting)
|
|
msleep(5);
|
|
if(result != GSIACAvailable)
|
|
{
|
|
MessageBox("The backend is not available\n");
|
|
return TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSbmfcsampleDlg::DestroyWindow()
|
|
{
|
|
// free the browser
|
|
if(m_serverBrowser)
|
|
{
|
|
ServerBrowserFree(m_serverBrowser);
|
|
m_serverBrowser = NULL;
|
|
}
|
|
|
|
return CDialog::DestroyWindow();
|
|
}
|
|
|
|
void CSbmfcsampleDlg::OnTimer(UINT nIDEvent)
|
|
{
|
|
// think if our timer was called
|
|
if(nIDEvent == m_timerID)
|
|
{
|
|
ServerBrowserThink(m_serverBrowser);
|
|
}
|
|
|
|
CDialog::OnTimer(nIDEvent);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::OnRefresh()
|
|
{
|
|
UpdateData();
|
|
|
|
// create the server list if we need to
|
|
if(!CreateServerList())
|
|
return;
|
|
|
|
// if we're doing an update, cancel it
|
|
SBState state = ServerBrowserState(m_serverBrowser);
|
|
if((state != sb_connected) && (state != sb_disconnected))
|
|
{
|
|
ServerBrowserHalt(m_serverBrowser);
|
|
return;
|
|
}
|
|
|
|
// clear the server browser and list
|
|
ServerBrowserClear(m_serverBrowser);
|
|
m_serverList.DeleteAllItems();
|
|
|
|
// clear the progress bar
|
|
m_progress.SetPos(0);
|
|
|
|
// clear the server count
|
|
m_serverCount = 0;
|
|
m_servers.SetWindowText("0");
|
|
|
|
// set a timer
|
|
if(!m_timerID)
|
|
m_timerID = SetTimer(TIMER_ID, TIMER_FREQUENCY, NULL);
|
|
|
|
// fields we're interested in
|
|
unsigned char fields[] = { HOSTNAME_KEY, NUMPLAYERS_KEY, MAXPLAYERS_KEY, MAPNAME_KEY, GAMETYPE_KEY };
|
|
int numFields = sizeof(fields) / sizeof(fields[0]);
|
|
|
|
// check for internet/lan
|
|
bool internet = (IsDlgButtonChecked(IDC_INTERNET) == BST_CHECKED);
|
|
|
|
// do an update
|
|
SBError error;
|
|
if(internet)
|
|
error = ServerBrowserUpdate(m_serverBrowser, SBTrue, SBFalse, fields, numFields, (char *)(const char *)m_filter);
|
|
else
|
|
error = ServerBrowserLANUpdate(m_serverBrowser, SBTrue, (unsigned short)m_startPort, (unsigned short)m_endPort);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::OnClickServerlist(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
// clear the player box
|
|
m_playerList.DeleteAllItems();
|
|
|
|
// find the selected server
|
|
POSITION pos = m_serverList.GetFirstSelectedItemPosition();
|
|
if(pos == NULL)
|
|
return;
|
|
int index = m_serverList.GetNextSelectedItem(pos);
|
|
|
|
// get the server
|
|
LVITEM item;
|
|
item.mask = LVIF_PARAM;
|
|
item.iItem = index;
|
|
item.iSubItem = 0;
|
|
m_serverList.GetItem(&item);
|
|
SBServer server = (SBServer)item.lParam;
|
|
|
|
if (!SBServerHasFullKeys(server)) //we need to query for the full rules
|
|
{
|
|
// turn on the hour glass
|
|
HCURSOR cursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
// do a server update (this is blocking!)
|
|
ServerBrowserAuxUpdateServer(m_serverBrowser, server, SBFalse, SBTrue);
|
|
|
|
// turn off the hour glass
|
|
SetCursor(cursor);
|
|
}
|
|
|
|
// get the player count
|
|
int count = SBServerGetIntValue(server, "numplayers", 0);
|
|
|
|
// add the players to the list
|
|
for(int i = 0 ; i < count ; i++)
|
|
{
|
|
m_playerList.InsertItem(0, SBServerGetPlayerStringValue(server, i, "player", "(NO NAME)"));
|
|
m_playerList.SetItem(0, COL_PPING, LVIF_TEXT, SBServerGetPlayerStringValue(server, i, "ping", "0"), -1, 0, 0, 0);
|
|
m_playerList.SetItem(0, COL_PSCORE, LVIF_TEXT, SBServerGetPlayerStringValue(server, i, "score", "0"), -1, 0, 0, 0);
|
|
}
|
|
|
|
// MFC
|
|
*pResult = 0;
|
|
|
|
GSI_UNUSED(pNMHDR);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::OnDblclkServerlist(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
// launch the game here
|
|
//MessageBox("If this were a real server browser, you would be launched now!","Go!");
|
|
|
|
// find the selected server
|
|
POSITION pos = m_serverList.GetFirstSelectedItemPosition();
|
|
if(pos == NULL)
|
|
return;
|
|
int index = m_serverList.GetNextSelectedItem(pos);
|
|
|
|
// get the server
|
|
LVITEM item;
|
|
item.mask = LVIF_PARAM;
|
|
item.iItem = index;
|
|
item.iSubItem = 0;
|
|
m_serverList.GetItem(&item);
|
|
SBServer server = (SBServer)item.lParam;
|
|
SBError error = ServerBrowserConnectToServer(m_serverBrowser, server, SBConnectCallback);
|
|
if(error != sbe_noerror)
|
|
MessageBox("Error starting connect to server");
|
|
|
|
// MFC
|
|
*pResult = 0;
|
|
|
|
GSI_UNUSED(pNMHDR);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::OnColumnclickServerlist(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
|
|
|
// track ascending/descending
|
|
static bool ascending = false;
|
|
ascending = !ascending;
|
|
|
|
//figure out which column they clicked
|
|
switch(pNMListView->iSubItem)
|
|
{
|
|
case COL_SERVERNAME:
|
|
ServerBrowserSort(m_serverBrowser, (SBBool)ascending, "hostname", sbcm_stricase);
|
|
break;
|
|
case COL_PING:
|
|
ServerBrowserSort(m_serverBrowser, (SBBool)ascending, "ping", sbcm_int);
|
|
break;
|
|
case COL_PLAYERS:
|
|
ServerBrowserSort(m_serverBrowser, (SBBool)ascending, "numplayers", sbcm_int);
|
|
break;
|
|
case COL_MAPNAME:
|
|
ServerBrowserSort(m_serverBrowser, (SBBool)ascending, "mapname", sbcm_stricase);
|
|
break;
|
|
case COL_GAMETYPE:
|
|
ServerBrowserSort(m_serverBrowser, (SBBool)ascending, "gametype", sbcm_stricase);
|
|
break;
|
|
}
|
|
|
|
// we don't want the server list to redraw every time we insert a server!
|
|
m_serverList.SetRedraw(false);
|
|
|
|
// clear the server list
|
|
m_serverList.DeleteAllItems();
|
|
|
|
// clear the server count
|
|
m_serverCount = 0;
|
|
m_servers.SetWindowText("0");
|
|
|
|
// go through the list of servers
|
|
for(int i = 0; i < ServerBrowserCount(m_serverBrowser) ; i++)
|
|
{
|
|
// if we got basic info for it, put it back in the list
|
|
SBServer server = ServerBrowserGetServer(m_serverBrowser, i);
|
|
if(SBServerHasBasicKeys(server))
|
|
AddServer(server, FALSE);
|
|
}
|
|
|
|
// let the server list redraw itself now that we're done updating
|
|
m_serverList.SetRedraw(true);
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
void CSbmfcsampleDlg::SBCallback(ServerBrowser serverBrowser, SBCallbackReason reason, SBServer server, void *instance)
|
|
{
|
|
CString str;
|
|
CSbmfcsampleDlg * dlg = (CSbmfcsampleDlg *)instance;
|
|
|
|
CString address;
|
|
if(server)
|
|
address.Format("%s:%d", SBServerGetPublicAddress(server), SBServerGetPublicQueryPort(server));
|
|
|
|
switch(reason)
|
|
{
|
|
case sbc_serveradded:
|
|
dlg->AddServer(server, TRUE);
|
|
break;
|
|
case sbc_serverupdated:
|
|
dlg->AddServer(server, TRUE);
|
|
break;
|
|
case sbc_serverupdatefailed:
|
|
break;
|
|
case sbc_serverdeleted:
|
|
dlg->RemoveServer(server);
|
|
break;
|
|
case sbc_updatecomplete:
|
|
dlg->m_progress.SetPos(100);
|
|
break;
|
|
case sbc_queryerror:
|
|
str.Format("Query Error: %s\n", ServerBrowserListQueryError(dlg->m_serverBrowser));
|
|
dlg->MessageBox(str);
|
|
break;
|
|
}
|
|
|
|
GSI_UNUSED(serverBrowser);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::SBConnectCallback(ServerBrowser serverBrowser, SBConnectToServerState state, SOCKET gamesocket, struct sockaddr_in *remoteaddr, void *instance)
|
|
{
|
|
CSbmfcsampleDlg * dlg = (CSbmfcsampleDlg *)instance;
|
|
|
|
switch(state)
|
|
{
|
|
case sbcs_succeeded:
|
|
dlg->MessageBox("Connected to server");
|
|
closesocket(gamesocket);
|
|
break;
|
|
case sbcs_failed:
|
|
dlg->MessageBox("Failed to connect to server");
|
|
break;
|
|
}
|
|
|
|
GSI_UNUSED(serverBrowser);
|
|
GSI_UNUSED(remoteaddr);
|
|
}
|
|
|
|
BOOL CSbmfcsampleDlg::CreateServerList()
|
|
{
|
|
// only create the object once
|
|
if(!m_serverBrowser)
|
|
{
|
|
// check for an empty gamename
|
|
if(m_gamename.IsEmpty())
|
|
{
|
|
MessageBox("No game specified");
|
|
GetDlgItem(IDC_GAMENAME)->SetFocus();
|
|
return FALSE;
|
|
}
|
|
SBBool lanBrowsing = (SBBool)(IsDlgButtonChecked(IDC_LAN) == BST_CHECKED);
|
|
if (m_startPort == 0 && lanBrowsing == SBTrue)
|
|
{
|
|
AfxMessageBox("Invalid start port!");
|
|
GetDlgItem(IDC_STARTP)->SetFocus();
|
|
return FALSE;
|
|
}
|
|
if (m_endPort == 0 && lanBrowsing == SBTrue)
|
|
{
|
|
AfxMessageBox("Invalid end port!");
|
|
GetDlgItem(IDC_ENDP)->SetFocus();
|
|
return FALSE;
|
|
}
|
|
|
|
// create it
|
|
m_serverBrowser = ServerBrowserNew(m_gamename, "gmtest", "HA6zkS", 0, MAX_UPDATES, (IsDlgButtonChecked(IDC_GOA) == BST_CHECKED)?QVERSION_GOA:QVERSION_QR2, lanBrowsing, SBCallback, this);
|
|
if(!m_serverBrowser)
|
|
{
|
|
MessageBox("Unable to create the server browser object");
|
|
return FALSE;
|
|
}
|
|
|
|
// don't let them change the gamename
|
|
GetDlgItem(IDC_GAMENAME)->EnableWindow(FALSE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CSbmfcsampleDlg::AddServer(SBServer server, BOOL checkForReplace)
|
|
{
|
|
// set the progress
|
|
if(ServerBrowserCount(m_serverBrowser) > 0)
|
|
m_progress.SetPos((ServerBrowserCount(m_serverBrowser) - ServerBrowserPendingQueryCount(m_serverBrowser)) * 100 / ServerBrowserCount(m_serverBrowser));
|
|
|
|
// check for the server in the list
|
|
int index = FindServer(server);
|
|
bool replace = (index != -1);
|
|
|
|
// if we didn't find a server to replace, append
|
|
if(!replace)
|
|
index = m_serverList.GetItemCount();
|
|
|
|
// set or insert the hostname
|
|
const char * hostname = SBServerGetStringValue(server, "hostname","(NO NAME)");
|
|
if(replace)
|
|
{
|
|
m_serverList.SetItem(index, COL_SERVERNAME, LVIF_TEXT, hostname, -1, 0, 0, NULL);
|
|
}
|
|
else
|
|
{
|
|
m_serverList.InsertItem(index, hostname);
|
|
m_serverList.SetItem(index, COL_SERVERNAME, LVIF_PARAM, NULL, -1, 0, 0, (LPARAM)server);
|
|
}
|
|
|
|
// set the rest of the columns
|
|
int numplayers = SBServerGetIntValue(server, "numplayers", 0);
|
|
CString ping, players;
|
|
if (SBServerHasValidPing(server))
|
|
ping.Format("%d%s", SBServerGetPing(server), SBServerDirectConnect(server) ? "" : "i");
|
|
else
|
|
ping = "Unknown";
|
|
players.Format("%d/%d", numplayers, SBServerGetIntValue(server, "maxplayers", 0));
|
|
m_serverList.SetItem(index, COL_PING, LVIF_TEXT, ping, -1, 0, 0, 0);
|
|
m_serverList.SetItem(index, COL_PLAYERS, LVIF_TEXT, players, -1, 0, 0, 0);
|
|
m_serverList.SetItem(index, COL_MAPNAME, LVIF_TEXT, SBServerGetStringValue(server, "mapname", "(NO MAP)"), -1, 0, 0, 0);
|
|
m_serverList.SetItem(index, COL_GAMETYPE, LVIF_TEXT, SBServerGetStringValue(server, "gametype", ""), -1, 0, 0, 0);
|
|
|
|
// update server count
|
|
if(!replace)
|
|
{
|
|
CString str;
|
|
str.Format("%d", ++m_serverCount);
|
|
m_servers.SetWindowText(str);
|
|
}
|
|
|
|
GSI_UNUSED(checkForReplace);
|
|
}
|
|
|
|
void CSbmfcsampleDlg::RemoveServer(SBServer server)
|
|
{
|
|
// find the server
|
|
int index = FindServer(server);
|
|
ASSERT(index != -1);
|
|
if(index == -1)
|
|
return;
|
|
|
|
// remove it
|
|
m_serverList.DeleteItem(index);
|
|
|
|
// update server count
|
|
CString str;
|
|
str.Format("%d", --m_serverCount);
|
|
m_servers.SetWindowText(str);
|
|
}
|
|
|
|
int CSbmfcsampleDlg::FindServer(SBServer server)
|
|
{
|
|
LVFINDINFO info;
|
|
info.flags = LVFI_PARAM;
|
|
info.lParam = (LPARAM)server;
|
|
return m_serverList.FindItem(&info);
|
|
}
|