?? core_network.cpp
字號:
/**************************************************
WinMain.cpp
GameCore Component
Programming Role-Playing Games with DirectX
by Jim Adams (Jan 2004)
**************************************************/
#include "Core_Global.h"
// Default application GUID
GUID g_ApplicationGUID = { 0x71118060, 0xfdb4, 0x11d4, { 0x90, 0x89, 0xeb, 0x5b, 0x75, 0x97, 0xe5, 0x70 } };
// This function sets a new application GUID
BOOL SetApplicationGUID(GUID *ApplicationGUID)
{
if(ApplicationGUID == NULL)
return FALSE;
memcpy(&g_ApplicationGUID, ApplicationGUID, sizeof(GUID));
return TRUE;
}
cNetworkAdapter::cNetworkAdapter()
{
m_AdapterList = NULL;
}
cNetworkAdapter::~cNetworkAdapter()
{
Shutdown();
}
BOOL cNetworkAdapter::Init()
{
IDirectPlay8Client *pDPClient = NULL;
DWORD dwSize = 0;
HRESULT hr;
Shutdown();
// Create DirectPlay Client component
if(FAILED(CoCreateInstance(CLSID_DirectPlay8Client, NULL, \
CLSCTX_INPROC, \
IID_IDirectPlay8Client, \
(void**)&pDPClient)))
return FALSE;
// Assign a message handler to network component
if(FAILED(pDPClient->Initialize(NULL, NetMsgHandler, 0))) {
pDPClient->Release();
return FALSE;
}
// Query the required size of the data buffer
if(pDPClient->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, m_AdapterList, &dwSize, &m_NumAdapters, 0) != DPNERR_BUFFERTOOSMALL) {
pDPClient->Release();
return FALSE;
}
// Allocate a buffer
if((m_AdapterList = (DPN_SERVICE_PROVIDER_INFO*)new BYTE[dwSize]) == NULL) {
pDPClient->Release();
return FALSE;
}
// Enumerate again
hr = pDPClient->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, m_AdapterList, &dwSize, &m_NumAdapters, 0);
// Release network interface
pDPClient->Release();
if(FAILED(hr))
return FALSE;
return TRUE;
}
BOOL cNetworkAdapter::Shutdown()
{
delete[] m_AdapterList;
m_AdapterList = NULL;
m_NumAdapters = 0;
return TRUE;
}
long cNetworkAdapter::GetNumAdapters()
{
return m_NumAdapters;
}
BOOL cNetworkAdapter::GetName(unsigned long Num, char *Buf)
{
if(m_AdapterList == NULL)
return FALSE;
if(Num >= m_NumAdapters)
return FALSE;
// Buf must be at least MAX_PATH bytes in size
wcstombs(Buf, m_AdapterList[Num].pwszName, MAX_PATH);
return TRUE;
}
GUID *cNetworkAdapter::GetGUID(unsigned long Num)
{
if(m_AdapterList == NULL)
return NULL;
if(Num >= m_NumAdapters)
return NULL;
return &m_AdapterList[Num].guid;
}
HRESULT WINAPI cNetworkAdapter::NetMsgHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer)
{
return S_OK;
}
cNetworkServer::cNetworkServer()
{
m_pDPServer = NULL;
m_Connected = FALSE;
m_Port = 0;
m_SessionName[0] = 0;
m_SessionPassword[0] = 0;
m_MaxPlayers = 0;
m_NumPlayers = 0;
}
cNetworkServer::~cNetworkServer()
{
Shutdown();
}
IDirectPlay8Server *cNetworkServer::GetServerCOM()
{
return m_pDPServer;
}
BOOL cNetworkServer::Init()
{
Shutdown();
// Create the Server object
if(FAILED(CoCreateInstance(CLSID_DirectPlay8Server, NULL, \
CLSCTX_INPROC, \
IID_IDirectPlay8Server, \
(void**)&m_pDPServer)))
return FALSE;
return TRUE;
}
BOOL cNetworkServer::Shutdown()
{
Disconnect();
// Release Server object
ReleaseCOM(m_pDPServer);
// Clear all member variables to default
m_pDPServer = NULL;
m_Connected = FALSE;
m_Port = 0;
m_SessionName[0] = 0;
m_SessionPassword[0] = 0;
m_MaxPlayers = 0;
m_NumPlayers = 0;
return TRUE;
}
BOOL cNetworkServer::Host(GUID *guidAdapter, long Port, char *SessionName, char *Password, long MaxPlayers)
{
DPN_APPLICATION_DESC dpad;
IDirectPlay8Address *pDPAddress;
WCHAR wSessionName[MAX_PATH], wPassword[MAX_PATH];
// Disconnect from current connection
Disconnect();
// Error checking
if(m_pDPServer == NULL)
return FALSE;
if(SessionName == NULL)
return FALSE;
// Get port selection
if(!(m_Port = Port))
return FALSE;
// Initialize the Server object
if(FAILED(m_pDPServer->Initialize((PVOID)this, NetworkMessageHandler, 0)))
return FALSE;
// Create an address object
if(FAILED(CoCreateInstance(CLSID_DirectPlay8Address, NULL, \
CLSCTX_INPROC, \
IID_IDirectPlay8Address, \
(void**)&pDPAddress)))
return FALSE;
// Set protocol
if(FAILED(pDPAddress->SetSP(&CLSID_DP8SP_TCPIP))) {
pDPAddress->Release();
return FALSE;
}
// Set the port - must not be 0
if(FAILED(pDPAddress->AddComponent(DPNA_KEY_PORT, &m_Port, sizeof(DWORD), DPNA_DATATYPE_DWORD))) {
pDPAddress->Release();
return FALSE;
}
// Set adapter (if any)
if(guidAdapter != NULL) {
if(FAILED(pDPAddress->AddComponent(DPNA_KEY_DEVICE, guidAdapter, sizeof(GUID), DPNA_DATATYPE_GUID))) {
pDPAddress->Release();
return FALSE;
}
}
// Record the session Name and Password
strcpy(m_SessionName, SessionName);
mbstowcs(wSessionName, SessionName, MAX_PATH);
if(Password != NULL) {
strcpy(m_SessionPassword, Password);
mbstowcs(wPassword, Password, MAX_PATH);
}
// Setup the application description structure
ZeroMemory(&dpad, sizeof(DPN_APPLICATION_DESC));
dpad.dwSize = sizeof(DPN_APPLICATION_DESC);
dpad.dwFlags = DPNSESSION_CLIENT_SERVER;
dpad.guidApplication = g_ApplicationGUID;
dpad.pwszSessionName = wSessionName;
if(Password != NULL) {
dpad.pwszPassword = wPassword;
dpad.dwFlags |= DPNSESSION_REQUIREPASSWORD;
}
dpad.dwMaxPlayers = (m_MaxPlayers = MaxPlayers);
// Start the hosting
if(FAILED(m_pDPServer->Host(&dpad, &pDPAddress, 1, NULL, NULL, NULL, 0))) {
pDPAddress->Release();
return FALSE;
}
pDPAddress->Release();
m_Connected = TRUE;
return TRUE;
}
BOOL cNetworkServer::Disconnect()
{
// Perform disconnect
if(m_pDPServer != NULL) {
if(FAILED(m_pDPServer->Close(0)))
return FALSE;
}
m_Connected = FALSE;
m_Port = 0;
m_SessionName[0] = 0;
m_SessionPassword[0] = 0;
m_MaxPlayers = 0;
m_NumPlayers = 0;
return TRUE;
}
BOOL cNetworkServer::IsConnected()
{
return m_Connected;
};
BOOL cNetworkServer::Send(DPNID dpnidPlayer, void *Data, unsigned long Size, unsigned long Flags)
{
DPNHANDLE hAsync;
DPN_BUFFER_DESC dpbd;
// Error checking
if(m_pDPServer == NULL)
return FALSE;
// Build a data structure
if((dpbd.dwBufferSize = Size) == 0)
return FALSE;
dpbd.pBufferData = (BYTE*)Data;
m_pDPServer->SendTo(dpnidPlayer, &dpbd, 1, 0, NULL, &hAsync, Flags);
return TRUE;
}
BOOL cNetworkServer::SendText(DPNID dpnidPlayer, char *Text, unsigned long Flags)
{
DPNHANDLE hAsync;
DPN_BUFFER_DESC dpbd;
// Error checking
if(m_pDPServer == NULL)
return FALSE;
// Build a data structure
dpbd.dwBufferSize = strlen(Text)+1;
dpbd.pBufferData = (BYTE*)Text;
m_pDPServer->SendTo(dpnidPlayer, &dpbd, 1, 0, NULL, &hAsync, Flags);
return TRUE;
}
BOOL cNetworkServer::DisconnectPlayer(long PlayerId)
{
// Error checking
if(m_pDPServer == NULL)
return FALSE;
// Try to disconnect the specified player
if(FAILED(m_pDPServer->DestroyClient(PlayerId, NULL, 0, 0)))
return FALSE;
return TRUE;
return TRUE;
}
BOOL cNetworkServer::GetIP(char *IPAddress, unsigned long PlayerNum)
{
WSADATA WSAData;
HOSTENT *HostEnt;
char LocalName[MAX_PATH], *LocalIP;
in_addr *LocalIPAddr;
IDirectPlay8Address *pDPAddress;
WCHAR ClientAddress[MAX_PATH];
DWORD Size, Flags;
// Get host IP address if PlayerNum == 0
if(!PlayerNum) {
if(WSAStartup(MAKEWORD(1,0), &WSAData))
return FALSE;
gethostname(LocalName, MAX_PATH);
if((HostEnt = gethostbyname(LocalName)) == NULL) {
WSACleanup();
return FALSE;
}
LocalIPAddr = (in_addr*)HostEnt->h_addr_list[0];
LocalIP = inet_ntoa(*LocalIPAddr);
WSACleanup();
if(LocalIP == NULL)
return FALSE;
strcpy(IPAddress, LocalIP);
return TRUE;
}
if(m_pDPServer == NULL)
return FALSE;
if(m_Connected == FALSE)
return FALSE;
// Retrieve the player information
if(FAILED(m_pDPServer->GetClientAddress((DPNID)PlayerNum, &pDPAddress, 0)))
return FALSE;
Size = MAX_PATH;
Flags = DPNA_DATATYPE_STRING;
if(FAILED(pDPAddress->GetComponentByName(DPNA_KEY_HOSTNAME, ClientAddress, &Size, &Flags))) {
pDPAddress->Release();
return FALSE;
}
wcstombs(IPAddress, ClientAddress, MAX_PATH);
pDPAddress->Release();
return TRUE;
}
BOOL cNetworkServer::GetName(char *Name, unsigned long PlayerId)
{
DPN_PLAYER_INFO *dppi;
DWORD Size;
HRESULT hr;
if(m_pDPServer == NULL)
return FALSE;
dppi = NULL;
Size = 0;
hr = m_pDPServer->GetClientInfo(PlayerId, dppi, &Size, 0);
if(FAILED(hr) && hr != DPNERR_BUFFERTOOSMALL)
return FALSE;
dppi = (DPN_PLAYER_INFO *)new char[Size];
dppi->dwSize = sizeof(DPN_PLAYER_INFO);
if(FAILED(m_pDPServer->GetClientInfo(PlayerId, dppi, &Size, 0))) {
delete[] dppi;
return FALSE;
}
wcstombs(Name, dppi->pwszName, MAX_PATH);
delete[] dppi;
return TRUE;
}
long cNetworkServer::GetPort()
{
return m_Port;
}
BOOL cNetworkServer::GetSessionName(char *Buf)
{
if(Buf == NULL)
return FALSE;
strcpy(Buf, m_SessionName);
return TRUE;
}
BOOL cNetworkServer::GetSessionPassword(char *Buf)
{
if(Buf == NULL)
return FALSE;
strcpy(Buf, m_SessionPassword);
return TRUE;
}
long cNetworkServer::GetMaxPlayers()
{
return m_MaxPlayers;
}
long cNetworkServer::GetNumPlayers()
{
return m_NumPlayers;
}
HRESULT WINAPI cNetworkServer::NetworkMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer)
{
cNetworkServer *Network;
if((Network = (cNetworkServer*)pvUserContext) == NULL)
return E_FAIL;
// Pass message to user-defined function
switch(dwMessageId) {
case DPN_MSGID_ADD_PLAYER_TO_GROUP:
if(Network->AddPlayerToGroup((DPNMSG_ADD_PLAYER_TO_GROUP *)pMsgBuffer) == TRUE)
return S_OK;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -