//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- E_NMSG* Network_GetPlayerData(DPID idPlayer) { HRESULT hr; if (g_pDPlay == NULL) return NULL; DWORD dwDataSize; E_NMSG* pNmsg = NULL; hr = g_pDPlay->GetPlayerData(idPlayer, NULL, &dwDataSize, DPGET_REMOTE); if (SUCCEEDED(hr)) { char* pTempData = new char[dwDataSize]; if (pTempData) { hr = g_pDPlay->GetPlayerData(idPlayer, pTempData, &dwDataSize, DPGET_REMOTE); if (SUCCEEDED(hr)) { pNmsg = Network_CreateNMSG(); if (pNmsg) { Network_FillNMSG(pNmsg, pTempData, dwDataSize); } } delete[] pTempData; } } return pNmsg; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL Network_DestroyPlayer() { HRESULT hRet; hRet = g_pDPlay->CancelMessage(0, 0); if (SUCCEEDED(hRet)) { hRet = g_pDPlay->DestroyPlayer(g_LocalPlayerID); if (SUCCEEDED(hRet)) return TRUE; } return FALSE; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- HRESULT Network_Receive(E_NMSG* pnmsg, BOOL* bRec, DPID* pFromID) { HRESULT hRet; pnmsg->pData = NULL; pnmsg->dwSize = 0; *bRec = FALSE; if (g_pDPlay == NULL) return S_OK; while (TRUE) { hRet = g_pDPlay->Receive(pFromID, &g_LocalPlayerID, DPRECEIVE_TOPLAYER, pnmsg->pData, &(pnmsg->dwSize)); if (hRet == DPERR_BUFFERTOOSMALL) { if (pnmsg->pData) { delete[] pnmsg->pData; pnmsg->pData = NULL; } pnmsg->pData = new char[pnmsg->dwSize]; if (!pnmsg->pData) return E_OUTOFMEMORY; continue; } if (hRet == DPERR_NOMESSAGES) return hRet; if (FAILED(hRet)) return hRet; *bRec = TRUE; break; } return hRet; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL FAR PASCAL DPConnect_EnumSessionsCallback(LPCDPSESSIONDESC2 pdpsd, DWORD* pdwTimeout, DWORD dwFlags, VOID* pvContext) { HRESULT hRet; if (dwFlags & DPESC_TIMEDOUT) return FALSE; if (strcmp(pdpsd->lpszSessionNameA, g_cDesc.szSessionName) == 0) { DPSESSIONDESC2 dpsd; memset(&dpsd, 0, sizeof(dpsd)); dpsd.dwSize = sizeof(dpsd); dpsd.guidInstance = pdpsd->guidInstance; dpsd.guidApplication = PXAPP_GUID; hRet = g_pDPlay->Open(&dpsd, DPOPEN_JOIN); if (FAILED(hRet)) return FALSE; *(BOOL*) pvContext = TRUE; return FALSE; //for stop enumerations } return TRUE; }
HRESULT bld_destroy_dp_interface(LPDIRECTPLAY4A dp_interface) { HRESULT hr = DP_OK; if (dp_interface) hr = dp_interface->Release(); return hr; }
void bld_enum_players(LPDIRECTPLAY4A dp_interface) { if (bld_is_server()) gbl_player_dpid = bld_get_player_dpid(); else dp_interface->EnumPlayers( NULL, bld_enum_players_cb, NULL, DPENUMPLAYERS_ALL ); }
HRESULT bld_create_player( LPDIRECTPLAY4A dp_interface, const char *game_name, const char *player_name, PLAYER_INFO *player_info ) { DPID dpid;/* the dpid of the player created given by directplay */ DPNAME name; HRESULT hr; DPSESSIONDESC2 session_desc; if (dp_interface == NULL) return DPERR_INVALIDOBJECT; ZeroMemory(&session_desc, sizeof(DPSESSIONDESC2)); session_desc.dwSize = sizeof(DPSESSIONDESC2); session_desc.dwFlags = (DPSESSION_KEEPALIVE | DPSESSION_MIGRATEHOST); session_desc.guidApplication = AppGUID; session_desc.dwMaxPlayers = gbl_max_players; session_desc.lpszSessionNameA = (char *)game_name; hr = dp_interface->Open(&session_desc, DPOPEN_CREATE); if (FAILED(hr)) goto close; ZeroMemory(&name,sizeof(DPNAME)); name.dwSize = sizeof(DPNAME); name.lpszShortNameA = (char *)player_name; name.lpszLongNameA = NULL; dp_interface->CreatePlayer( &dpid, &name, player_info->event, NULL, 0, DPPLAYER_SERVERPLAYER ); if (FAILED(hr)) goto close; player_info->dp_interface = dp_interface; player_info->dpid = dpid; player_info->is_server = 1; return DP_OK; close: dp_interface->Close(); return hr; }
HRESULT bld_create_client_player( LPDIRECTPLAY4A dp_interface, LPGUID sessionGuid, const char *player_name, PLAYER_INFO *player_info) { DPID dpid;/* the dpid of the player created given by directplay */ DPNAME name; HRESULT hr; DPSESSIONDESC2 session_desc; if (dp_interface == NULL) return DPERR_INVALIDOBJECT; ZeroMemory(&session_desc, sizeof(DPSESSIONDESC2)); session_desc.dwSize = sizeof(DPSESSIONDESC2); session_desc.guidInstance = *sessionGuid; player_info->dp_interface = dp_interface; hr = dp_interface->Open(&session_desc, DPOPEN_JOIN); if (FAILED(hr)) goto close; ZeroMemory(&name,sizeof(DPNAME)); name.dwSize = sizeof(DPNAME); name.lpszShortNameA = (char *)player_name; name.lpszLongNameA = NULL; dp_interface->CreatePlayer( &dpid, &name, player_info->event, NULL, 0, 0 ); if (FAILED(hr)) goto close; player_info->dpid = dpid; player_info->is_server = 0; return DP_OK; close: dp_interface->Close(); return hr; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL Network_CloseSession() { HRESULT hRet; hRet = g_pDPlay->Close(); if (FAILED(hRet)) return FALSE; return TRUE; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- void Network_Free() { if (g_pDPlay) { g_pDPlay->Close(); SAFE_RELEASE(g_pDPlay); } if (g_hEvent != 0) { CloseHandle(g_hEvent); g_hEvent = 0; } }
//----------------------------------------------------------------------------- // Name: // Desc: change local player data //----------------------------------------------------------------------------- BOOL Network_SetPlayerData(void* pData, DWORD dwSize) { HRESULT hRet; if (g_pDPlay == NULL) return FALSE; hRet = g_pDPlay->SetPlayerData(g_LocalPlayerID, pData, dwSize, DPSET_GUARANTEED | DPSET_REMOTE); if (FAILED( hRet)) return FALSE; return TRUE; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL Network_Send(void* pData, DWORD dwSize) { HRESULT hRet; if (g_pDPlay == NULL) return FALSE; hRet = g_pDPlay->SendEx(g_LocalPlayerID, DPID_ALLPLAYERS, DPSEND_ASYNC | DPSEND_GUARANTEED | DPSEND_NOSENDCOMPLETEMSG, pData, dwSize, 0, NULL, NULL, NULL); if (FAILED (hRet)) return FALSE; return TRUE; }
HRESULT bld_enum_sessions(LPDIRECTPLAY4A dp_interface) { HRESULT hr; DPSESSIONDESC2 session_desc; if (dp_interface == NULL) return DPERR_INVALIDOBJECT; gbl_num_sessions = 0; ZeroMemory(&session_desc, sizeof(DPSESSIONDESC2)); session_desc.dwSize = sizeof(DPSESSIONDESC2); session_desc.guidApplication = AppGUID; hr = dp_interface->EnumSessions( &session_desc, 0, bld_enum_sessions_cb, NULL, DPENUMSESSIONS_AVAILABLE ); return hr; }
//----------------------------------------------------------------------------- // Name: // Desc: create local player //----------------------------------------------------------------------------- BOOL Network_CreatePlayer(const char* pszPlayerName) { DPNAME dpname; HRESULT hRet; if (g_pDPlay == NULL) return FALSE; strcpy(g_cDesc.szPlayerName, pszPlayerName); g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); memset(&dpname, 0, sizeof(DPNAME)); dpname.dwSize = sizeof(DPNAME); dpname.lpszShortNameA = g_cDesc.szPlayerName; hRet = g_pDPlay->CreatePlayer(&g_LocalPlayerID, &dpname, g_hEvent, NULL, 0, 0); if (FAILED(hRet)) return FALSE; return TRUE; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL Network_GetSessionsStats(NM_SESSIONS_STATS* pStats) { if (pStats == NULL) return FALSE; DPSESSIONDESC2 dpsd; HRESULT hRet; memset(&dpsd, 0, sizeof(dpsd)); dpsd.dwSize = sizeof(dpsd); dpsd.guidApplication = PXAPP_GUID; pStats->iRealSize = 0; hRet = g_pDPlay->EnumSessions(&dpsd, 0, DPConnect_EnumStatsCallback, pStats, DPENUMSESSIONS_ALL); if (FAILED(hRet)) return FALSE; return TRUE; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL Network_ConnectToSession(const char* pszSessionName, const char* pcszServerIP) { DPSESSIONDESC2 dpsd; HRESULT hRet; BOOL bCon = FALSE; if (!nm_InitConnection(pcszServerIP)) return FALSE; g_cDesc.bIsServer = FALSE; strcpy(g_cDesc.szSessionName, pszSessionName); memset(&dpsd, 0, sizeof(dpsd)); dpsd.dwSize = sizeof(dpsd); dpsd.guidApplication = PXAPP_GUID; hRet = g_pDPlay->EnumSessions(&dpsd, 0, DPConnect_EnumSessionsCallback, &bCon, DPENUMSESSIONS_ALL); if (FAILED(hRet)) return FALSE; return bCon; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- BOOL Network_CreateSession(const char* pszSessionName, int nMaxPlayers) { DPSESSIONDESC2 dpsd; HRESULT hRet; if (!nm_InitConnection(NULL)) return FALSE; strcpy(g_cDesc.szSessionName, pszSessionName); g_cDesc.bIsServer = TRUE; memset(&dpsd, 0, sizeof(dpsd)); dpsd.dwSize = sizeof(dpsd); dpsd.lpszSessionNameA = g_cDesc.szSessionName; dpsd.guidApplication = PXAPP_GUID; dpsd.dwMaxPlayers = nMaxPlayers; dpsd.dwFlags = DPSESSION_KEEPALIVE; hRet = g_pDPlay->Open(&dpsd, DPOPEN_CREATE); if (FAILED(hRet)) return FALSE; return TRUE; }
bool bld_browse_sessions(const char *ip_address) { DWORD lpConnectionSize; char lpConnection[128]; HRESULT hr; LPDIRECTPLAYLOBBYA lpdplobby; GUID dp_provider; lpConnectionSize = sizeof(lpConnection); hr = bld_create_thread(); if (FAILED(hr)) goto cleanup; if (gbl_dp_interface == NULL) { if (ip_address) dp_provider = GUID_NULL; else dp_provider = DPSPGUID_IPX; hr = bld_create_dp_interface(&dp_provider, &gbl_dp_interface); bld_assert_result(hr); if (FAILED(hr)) goto cleanup; } if (ip_address) { if (gbl_player_info.dp_lobby == NULL) { // creating lobby object hr = DirectPlayLobbyCreateA( NULL, &lpdplobby, NULL, NULL, 0 ); if (FAILED(hr)) goto cleanup; // get new interface of lobby hr = lpdplobby->QueryInterface( IID_IDirectPlayLobby3A, (LPVOID *)&gbl_player_info.dp_lobby ); // release old interface since we have new one lpdplobby->Release(); if (FAILED(hr)) goto cleanup; } hr = gbl_player_info.dp_lobby->CreateAddress( DPSPGUID_TCPIP, DPAID_INet, ip_address, strlen(ip_address), &lpConnection, &lpConnectionSize ); if (FAILED(hr)) goto cleanup; hr = gbl_dp_interface->InitializeConnection(&lpConnection, 0); bld_assert_result(hr); if (FAILED(hr)) goto cleanup; } hr = bld_enum_sessions(gbl_dp_interface); if (FAILED(hr)) goto cleanup; return true; cleanup: if (gbl_player_info.dp_lobby) gbl_player_info.dp_lobby->Release(); gbl_player_info.dp_lobby = NULL; bld_destroy_dp_interface(gbl_dp_interface); gbl_dp_interface = NULL; return false; }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- static BOOL nm_InitConnection(const char* pcszServerIP) { HRESULT hRet; LPDIRECTPLAYLOBBY3A pDPLobby = NULL; // Create a ANSI DirectPlay interface hRet = CoCreateInstance(CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (VOID**)&g_pDPlay); if (FAILED(hRet)) return FALSE; // Get ANSI DirectPlayLobby interface hRet = CoCreateInstance(CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A, (VOID**)&pDPLobby); if (FAILED(hRet)) return FALSE; DPCOMPOUNDADDRESSELEMENT addressElements[3]; CHAR strIPAddressString[MAX_BUFFER]; VOID* pAddress = NULL; DWORD dwAddressSize = 0; DWORD dwElementCount = 0; // TCP/IP needs a service provider, an IP address // Service provider addressElements[dwElementCount].guidDataType = DPAID_ServiceProvider; addressElements[dwElementCount].dwDataSize = sizeof(GUID); addressElements[dwElementCount].lpData = (VOID*)&DPSPGUID_TCPIP; dwElementCount++; // IP address string if (pcszServerIP != NULL) { lstrcpy(strIPAddressString, pcszServerIP); } else { lstrcpy(strIPAddressString, ""); } addressElements[dwElementCount].guidDataType = DPAID_INet; addressElements[dwElementCount].dwDataSize = lstrlen(strIPAddressString) + 1; addressElements[dwElementCount].lpData = strIPAddressString; dwElementCount++; // See how much room is needed to store this address hRet = pDPLobby->CreateCompoundAddress(addressElements, dwElementCount, NULL, &dwAddressSize); if (hRet != DPERR_BUFFERTOOSMALL) { SAFE_RELEASE(pDPLobby); return FALSE; } // Allocate space pAddress = GlobalAllocPtr(GHND, dwAddressSize); if (pAddress == NULL) { SAFE_RELEASE(pDPLobby); return FALSE; } // Create the address hRet = pDPLobby->CreateCompoundAddress(addressElements, dwElementCount, pAddress, &dwAddressSize); if (FAILED(hRet)) { SAFE_RELEASE(pDPLobby); GlobalFreePtr(pAddress); return FALSE; } // initialize connection hRet = g_pDPlay->InitializeConnection(pAddress, 0); if (FAILED(hRet)) { SAFE_RELEASE(pDPLobby); GlobalFreePtr(pAddress); return FALSE; } return TRUE; }