⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameservdlg.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// GameServDlg.cpp : implementation file
//


// Includes...

#include "stdafx.h"
#include "coolserv.h"
#include "GameServDlg.h"
#include "NetStart.h"
#include "Sparam.h"
#include "Utils.h"
#include "mmsystem.h"


// Defines...

#define DEFAULT_PORT	27888
#define USE_POSTMSG		0


// Debug...

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


// Macros...

#define DEC_TIMER(t, d)		if (d >= t) t = 0; else t -= d;


// Externs...

extern	ServerInfo		g_ServerInfo;
extern	ServerOptions	g_ServerOptions;
extern	NetGame			g_NetGame;
extern	BOOL	 		g_bEmptyExit;


// Globals...

DWORD	g_timeCur   = 0;
DWORD	g_timeLast  = 0;
DWORD	g_timeDelta = 0;
DWORD	g_timeStart = 0;

DWORD	g_dwPosted  = 0;
DWORD	g_dwHandled = 0;
DWORD	g_dwRemoved = 0;

BOOL	g_bDoEmptyExit    = FALSE;
int		g_nEmptyExitDelay = 60;
DWORD	g_timerEmptyExit  = 0;
BOOL	g_bNoExitConfirm  = FALSE;

CString	g_sFullTcpIpAddress;
WORD	g_wPort = 0;

#define SERVER_VERSION	"2.1"
#define DEFAULT_PORT	27888

CString	g_sSpyGameName;
CString	g_sSpyGameVer;
CString	g_sSpyGameKey;
CString g_sWebGameName;
CString	g_sWebGameVer;
CString g_sWebRegUrl;


// Statics...

static	DWORD	s_timerWebRegUpdate  = 400; 

static	BOOL	s_bThreadDone = FALSE;


// Classes...

class CGameServerAppHandler : public ServerAppHandler
{
public:
	DRESULT ShellMessageFn(char* pInfo);
	DRESULT ConsoleOutputFn(char* pInfo);
	DRESULT	OutOfMemory();
	DRESULT ProcessPacket(char *pData, DDWORD dataLen, DBYTE senderAddr[4], D_WORD senderPort);
};


// Globals...

CGameServDlg*			g_pDialog = NULL;
CGameServerAppHandler	g_AppHandler;


// Prototypes...

DWORD WINAPI ThreadUpdate(LPVOID lpParameter);


// Functions...

DRESULT CGameServerAppHandler::ShellMessageFn(char* pInfo)
{
	if (g_pDialog)
	{
		g_pDialog->OnShellMessage(pInfo);
	}

	return(LT_OK);
}

DRESULT CGameServerAppHandler::ConsoleOutputFn(char* pInfo)
{
	if (g_pDialog)
	{
		g_pDialog->OnConsoleOutput(pInfo);
	}

	return(LT_OK);
}

DRESULT CGameServerAppHandler::OutOfMemory()
{
	if (g_pDialog)
	{
		g_pDialog->OnOutOfMemory();
	}

	return(LT_OK);
}

DRESULT CGameServerAppHandler::ProcessPacket(char *pData, DDWORD dataLen, DBYTE senderAddr[4], D_WORD senderPort)
{
	if(g_pDialog)
	{
		g_pDialog->OnProcessNetPacket(pData, dataLen, senderAddr, senderPort);
	}

	return LT_OK;
}





// ----------------------------------------------------------------------- //
// Replacement for MFC's trace.  Doesn't ASSERT.
// ----------------------------------------------------------------------- //

void SS_Trace(const char *pMsg, ...)
{
	#ifdef _DEBUG
		char buf[1024*16];
		va_list marker;

		va_start(marker, pMsg);
		vsprintf(buf, pMsg, marker);
		va_end(marker);

		OutputDebugString(buf);
	#endif
}


/////////////////////////////////////////////////////////////////////////////
// CGameServSendHandler
/////////////////////////////////////////////////////////////////////////////

void CGameServSendHandler::SendTo(const void *pData, unsigned long len, const char *sAddr, unsigned long port)
{
	ServerInterface *pMgr;

	if(m_pDlg && (pMgr = m_pDlg->GetServerMgr()))
	{
		pMgr->SendTo(pData, len, sAddr, port);
	}
}



/////////////////////////////////////////////////////////////////////////////
// CGameServDlg dialog

CGameServDlg::CGameServDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGameServDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CGameServDlg)
	//}}AFX_DATA_INIT

	Clear();

	m_pConfigFilename = NULL;
	g_pDialog = this;
	m_SendHandler.SetDlg(this);

	m_sGameSpyGameMode = "openplaying";
	m_sGameSpyGameType = "deathmatch";
}


void CGameServDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGameServDlg)
	DDX_Control(pDX, IDC_PLAYERS_LIST, m_lbPlayers);
	DDX_Control(pDX, IDC_LEVELS_LIST, m_lbLevels);
	DDX_Control(pDX, IDC_CONSOLE_WINDOW, m_edConsole);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CGameServDlg, CDialog)
	//{{AFX_MSG_MAP(CGameServDlg)
	ON_WM_SHOWWINDOW()
	ON_WM_CLOSE()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_QUIT, OnQuit)
	ON_BN_CLICKED(IDC_SERVER, OnServer)
	ON_BN_CLICKED(IDC_CONSOLE_SEND, OnConsoleSend)
	ON_BN_CLICKED(IDC_CONSOLE_CLEAR, OnConsoleClear)
	ON_BN_CLICKED(IDC_COMMANDS_NEXTLEVEL, OnCommandsNextLevel)
	ON_BN_CLICKED(IDC_PLAYERS_BOOT, OnPlayersBoot)
	ON_LBN_SELCHANGE(IDC_PLAYERS_LIST, OnSelchangePlayersList)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_COMMANDS_OPTIONS, OnCommandsOptions)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


BOOL CGameServDlg::Init()
{
	if(!m_bCSInitted)
	{
		InitializeCriticalSection(&m_CS);
		m_bCSInitted = TRUE;
	}
	
	// Display a console message...

	WriteConsoleString(IDS_CONSOLE_INITSERVER);


	// Get the server interface...

	m_pServerMgr = GetServerInterface();
	if (!m_pServerMgr) return(FALSE);


	// Set our app handler...

	m_pServerMgr->SetAppHandler(&g_AppHandler);


	// Set the tab stops for the player list box...

	int nTabs[10] = { 30, 116, 181, 84, 86, 88, 90, 92, 94, 96 };

	m_lbPlayers.SetTabStops(10, nTabs);


	// Load some strings...

	g_sSpyGameName.LoadString(IDS_SPYGAMENAME);
	g_sSpyGameKey.LoadString(IDS_SPYGAMEKEY);
	g_sWebRegUrl.LoadString(IDS_WEBREGURL);

#ifdef _ADDON
	g_sSpyGameVer.LoadString(IDS_SPYGAMEVER_AO);
	g_sWebGameName.LoadString(IDS_WEBGAMENAME_AO);
	g_sWebGameVer.LoadString(IDS_WEBGAMEVER_AO);
#else
	g_sSpyGameVer.LoadString(IDS_SPYGAMEVER);
	g_sWebGameName.LoadString(IDS_WEBGAMENAME);
	g_sWebGameVer.LoadString(IDS_WEBGAMEVER);
#endif


	// All done...

	WriteConsoleString(IDS_CONSOLE_SERVERINITED);
	return(TRUE);
}

void CGameServDlg::Term()
{
	if(m_bCSInitted)
	{
		DeleteCriticalSection(&m_CS);
		m_bCSInitted = FALSE;
	}

	Clear();
	g_pDialog = NULL;

	Sleep(2);
	SS_Trace("Updates posted  = %lu\n", g_dwPosted);
	SS_Trace("Updates handled = %lu\n", g_dwHandled);
	SS_Trace("Updates removed = %lu\n", g_dwRemoved);
	SS_Trace("Updates per sec = %i\n", (int)((float)(g_dwHandled / (float)(timeGetTime() - g_timeStart)) * 1000));
}

void CGameServDlg::Clear()
{
	m_bCSInitted = FALSE;
	memset(&m_CS, 0, sizeof(m_CS));

	m_pServerMgr = NULL;
	g_pDialog    = NULL;

	m_bRunning       = FALSE;
	m_bLevelChanging = FALSE;

	m_timeServerRunning = 0;
	m_timeServerStart   = 0;
	m_timeServerLast    = 0;

	m_timeLevelRunning = 0;
	m_timeLevelStart   = 0;
	m_timeLevelLast    = 0;

	m_cPlayers  = 0;
	m_nCurLevel = 0;

	m_hThread    = NULL;
	m_dwThreadID = NULL;

	m_sCurLevel.Empty();
}

BOOL CGameServDlg::StartServer()
{
	// Sanity checks...

	if (!m_pServerMgr) return(FALSE);


	// Set the debug level...

	m_pServerMgr->RunConsoleString("debuglevel 0");


	// Set the server options...

	NetStart_RunServerOptions(m_pServerMgr, &g_ServerOptions);


	// Set the game type string based on the game type...

	int nStringID = IDS_GAMETYPE_DEATHMATCH;

	switch (g_NetGame.m_byType)
	{
		case NGT_CAPTUREFLAG:	nStringID = IDS_GAMETYPE_CAPTUREFLAG; break;
		case NGT_COOPERATIVE:	nStringID = IDS_GAMETYPE_COOPERATIVE; break;
		case NGT_TEAMS:			nStringID = IDS_GAMETYPE_TEAM; break;

#ifdef _ADDON
		case NGT_SOCCER:		nStringID = IDS_GAMETYPE_SOCCER; break;
#endif

	}

	m_sGameSpyGameType.LoadString(nStringID);


	// Look at some console vars...

	HCONSOLEVAR hVar = NULL;

	DRESULT dr = m_pServerMgr->GetConsoleVar("WebRegUpdate", &hVar, NULL);
	if (dr == LT_OK && hVar)
	{
		float fVal = 0;
		dr = m_pServerMgr->GetVarValueFloat(hVar, &fVal);
		if (dr == LT_OK && fVal > 1)
		{
			s_timerWebRegUpdate = (DWORD)fVal;
		}
	}

	hVar = NULL;
	dr   = m_pServerMgr->GetConsoleVar("EmptyExit", &hVar, NULL);
	if (dr == LT_OK && hVar)
	{
		float fVal = 0;
		dr = m_pServerMgr->GetVarValueFloat(hVar, &fVal);
		if (dr == LT_OK && fVal >= 1)
		{
			g_bEmptyExit = TRUE;
		}
	}

	hVar = NULL;
	dr   = m_pServerMgr->GetConsoleVar("EmptyExitDelay", &hVar, NULL);
	if (dr == LT_OK && hVar)
	{
		float fVal = 0;
		dr = m_pServerMgr->GetVarValueFloat(hVar, &fVal);
		if (dr == LT_OK && fVal >= 1)
		{
			g_nEmptyExitDelay = (int)fVal;
		}
	}

	hVar = NULL;
	dr   = m_pServerMgr->GetConsoleVar("SpyGameType", &hVar, NULL);
	if (dr == LT_OK && hVar)
	{
		char sTemp[64] = { "" };
		dr = m_pServerMgr->GetVarValueString(hVar, sTemp, 64);
		if (dr == LT_OK && sTemp[0] != '\0')
		{
			m_sGameSpyGameType = sTemp;
		}
	}

	hVar = NULL;
	dr   = m_pServerMgr->GetConsoleVar("SpyGameMode", &hVar, NULL);
	if (dr == LT_OK && hVar)
	{
		char sTemp[64] = { "" };
		dr = m_pServerMgr->GetVarValueString(hVar, sTemp, 64);
		if (dr == LT_OK && sTemp[0] != '\0')
		{
			m_sGameSpyGameMode = sTemp;
		}
	}


	// Host the game...

	CWaitCursor wc;

	NetHost nh;

	memset(&nh, 0, sizeof(nh));

	nh.m_dwMaxPlayers = g_ServerInfo.m_dwMaxPlayers;
	nh.m_Port         = NetStart_GetPort();

	CString sHost;

#ifdef _ADDON
	sHost.LoadString(IDS_APPNAME_AO);
#else
	sHost.LoadString(IDS_APPNAME);
#endif

	Sparam_Add(nh.m_sName, NST_GAMENAME,  g_ServerInfo.m_sName);
	Sparam_Add(nh.m_sName, NST_GAMEHOST,  sHost);
	Sparam_Add(nh.m_sName, NST_GAMELEVEL, g_NetGame.m_sLevels[0]);
	Sparam_Add(nh.m_sName, NST_GAMETYPE,  g_NetGame.m_byType);

	if (m_pServerMgr->HostGame(&nh) != DTRUE)
	{
		WriteConsoleString(IDS_CONSOLE_UNABLETOHOST);
		StopServer();
		return(FALSE);
	}


	// Start the world...

	StartGameRequest req;
	memset(&req, 0, sizeof(req));

	req.m_Type = STARTGAME_HOST;
	req.m_pGameInfo   = &g_NetGame;
	req.m_GameInfoLen = sizeof(NetGame_t);

	strcpy(req.m_WorldName, g_NetGame.m_sLevels[0]);

	if (m_pServerMgr->StartWorld(&req) != DTRUE)
	{
		WriteConsoleString(IDS_CONSOLE_UNABLETOSTARTWORLD);
		WriteConsoleString(req.m_WorldName);
		StopServer();
		return(FALSE);
	}


	// Update the service info with the tcp/ip address if available...

	g_ServerInfo.m_sAddress[0] = '\0';
	g_wPort = 0;

	m_pServerMgr->GetTcpIpAddress(g_ServerInfo.m_sAddress, 128, g_wPort);

	CString sService    = g_ServerInfo.m_sService;
	g_sFullTcpIpAddress = "";
	if (g_ServerInfo.m_sAddress[0] != '\0')
	{
		sService += " ";
		g_sFullTcpIpAddress = g_ServerInfo.m_sAddress;
		if (g_wPort > 0 && g_wPort != DEFAULT_PORT)
		{
			char sTemp[32];
			wsprintf(sTemp, ":%i", g_wPort);
			g_sFullTcpIpAddress += sTemp;
		}
		sService += "[";
		sService += g_sFullTcpIpAddress;
		sService += "]";
	}
	SetDlgItemText(IDC_SERVER_SERVICE, sService);


	// Tell the server shell to update the game info parameters...

	m_pServerMgr->SendToServerShell("GAMEINIT");


	// Tell the server that this is a stand-alone server hosted game...

	m_pServerMgr->SendToServerShell("SERVHOST");


	// Init some stuff now that we're running...

	m_bRunning        = TRUE;
	m_timeServerStart = timeGetTime();
	g_timeStart       = timeGetTime();
	m_timeLevelStart  = m_timeServerStart;


	// Init the GameSpy manager...

	if (g_ServerInfo.m_bUseGameSpy)
	{
		if (m_GameSpyMgr.Init(g_sSpyGameName, g_sSpyGameVer, g_sSpyGameKey, 0, g_wPort, (g_wPort+166), GSMF_USEGAMEPORTFORHEARTBEAT))
		{
			m_GameSpyMgr.SetSendHandler(&m_SendHandler);
		}
		else
		{
			g_ServerInfo.m_bUseGameSpy = FALSE;
		}
	}


	// Create the thread to do our updating...

	m_hThread = CreateThread(NULL, 0, ThreadUpdate, (void*)g_pDialog, 0, &m_dwThreadID);


	// All done...

	WriteConsoleString(IDS_CONSOLE_SERVERRUNNING);
	return(TRUE);
}

BOOL CGameServDlg::StopServer()
{
	// Unregister the server if necessary...

	if (m_bRunning)
	{
		UnregisterServer();
	}


	// Terminate the GameSpy manager...

	m_GameSpyMgr.Term();


	// Flag that we are done...

	m_bRunning = FALSE;


	// Wait for the thread to stop...

	if (m_hThread)
	{
		Sleep(0);
		DWORD dwRet = WaitForSingleObject(m_hThread, 1000);
		Sleep(0);
		
		if (dwRet == WAIT_OBJECT_0)
		{
			CloseHandle(m_hThread);
		}
		else
		{
			TerminateThread(m_hThread, 0);
		}

		m_hThread = NULL;
	}


	// All done...

	return(TRUE);
}

void CGameServDlg::WriteConsoleString(LPCTSTR pMsg, ...)
{
	TCHAR		str[500];
	va_list		marker;
	int			nLen;

	static int nMax = 500;

	if(m_edConsole.GetLineCount() > nMax)
	{
		// Nuke the oldest 75%.
		int iLine = (m_edConsole.GetLineCount()*75) / 100;
		int iChar = m_edConsole.LineIndex(iLine);
		
		m_edConsole.SetRedraw(FALSE);
		m_edConsole.SetSel(0, iChar);
		m_edConsole.ReplaceSel("", FALSE);
		m_edConsole.SetRedraw(TRUE);
	}

	va_start(marker, pMsg);
	vsprintf(str, pMsg, marker);
	va_end(marker);

	int len = strlen(str);
	if (len <= 0) return;
	if (len > 0 && str[len-1] < 32) str[len-1] = '\0';

	strcat(str, "\r\n");

	nLen = m_edConsole.SendMessage(EM_GETLIMITTEXT, 0, 0);
	m_edConsole.SetSel(nLen, nLen);
	m_edConsole.ReplaceSel(str);
}

void CGameServDlg::WriteConsoleString(int nStringID)
{
	CString sMsg;
	if (!sMsg.LoadString(nStringID)) return;
	WriteConsoleString(sMsg);
}

/////////////////////////////////////////////////////////////////////////////
// CGameServDlg message handlers

BOOL CGameServDlg::OnInitDialog() 
{
	// Let the base class do it's thing...

	CDialog::OnInitDialog();


	// Set the window title if necessary...

#ifdef _ADDON
	CString sTitle;
	sTitle.LoadString(IDS_DIALOGTITLE_AO);
	SetWindowText(sTitle);
#endif


	// Fill in some of the text info...

	SetDlgItemText(IDC_SERVER_NAME, g_ServerInfo.m_sName);
	SetDlgItemText(IDC_SERVER_TIME, "0:00");

	CString sService(g_ServerInfo.m_sService);
	if (g_ServerInfo.m_sAddress[0] != '\0')
	{
		sService += " (";
		sService += g_ServerInfo.m_sAddress;
		sService += ")";
	}
	SetDlgItemText(IDC_SERVER_SERVICE, sService);

	SetDlgItemText(IDC_GAME_PLAYERS, "0");
	SetDlgItemText(IDC_GAME_CURLEVEL, g_NetGame.m_sLevels[0]);
	SetDlgItemText(IDC_GAME_TIME, "0:00");

	m_sCurLevel = g_NetGame.m_sLevels[0];

	if (g_NetGame.m_byNumLevels > 1) SetDlgItemText(IDC_GAME_NEXTLEVEL, g_NetGame.m_sLevels[1]);
	else SetDlgItemText(IDC_GAME_NEXTLEVEL, "");

	CString sBuf;
	if (g_NetGame.m_byEnd == NGE_FRAGS) sBuf.Format("%i Frags", g_NetGame.m_dwEndFrags);
	else if (g_NetGame.m_byEnd == NGE_TIME) sBuf.Format("%i Minutes", g_NetGame.m_dwEndTime);
	else if (g_NetGame.m_byEnd == NGE_FRAGSANDTIME) sBuf.Format("%i Frags or %i Minutes", g_NetGame.m_dwEndFrags, g_NetGame.m_dwEndTime);
	else sBuf = "None. Level never ends.";
	SetDlgItemText(IDC_GAME_GOAL, sBuf);

	for (int i = 0; i < g_NetGame.m_byNumLevels; i++)
	{
		m_lbLevels.AddString(g_NetGame.m_sLevels[i]);
	}


	// Set the icon...

	HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	SetIcon(hIcon, TRUE);
	SetIcon(hIcon, FALSE);


	for(i=0; i < 30; i++)
	{
		if(SetTimer((UINT)i, 500, NULL))
			break;
	}

	// All done...

	return(TRUE);
}

BOOL CGameServDlg::OnCommand(WPARAM wParam, LPARAM lParam) 
{
	switch (wParam)
	{
		case ID_INIT:
		{
			if (!Init())
			{
				return(TRUE);
			}

			if (!StartServer())
			{
				return(TRUE);
			}

			return(TRUE);
		}

		case ID_UPDATE:
		{
			OnUpdate();
			return(TRUE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -