multiplay_setup.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. #include "std.h"
  2. #include "bbsys.h"
  3. #include "resource.h"
  4. #include "multiplay_setup.h"
  5. IDirectPlay4 *dirPlay;
  6. struct Connection{
  7. GUID guid;
  8. string name;
  9. void *data;
  10. Connection( const GUID &g,const string &n,void *d,int sz ):guid(g),name(n){
  11. data=d_new char[sz];memcpy( data,d,sz );
  12. }
  13. ~Connection(){
  14. delete[] data;
  15. }
  16. };
  17. struct Session{
  18. GUID guid;
  19. string name;
  20. int max_players,curr_players,data1,data2;
  21. Session( const DPSESSIONDESC2 *desc ){
  22. guid=desc->guidInstance;
  23. name=string( desc->lpszSessionNameA );
  24. max_players=desc->dwMaxPlayers;
  25. curr_players=desc->dwCurrentPlayers;
  26. data1=desc->dwUser1;data2=desc->dwUser2;
  27. }
  28. };
  29. static int timer;
  30. static vector<Connection*> connections;
  31. static vector<Session*> sessions;
  32. static void clearSessions(){
  33. for( ;sessions.size();sessions.pop_back() ) delete sessions.back();
  34. }
  35. static void clearConnections(){
  36. for( ;connections.size();connections.pop_back() ) delete connections.back();
  37. }
  38. static bool openDirPlay( HWND hwnd ){
  39. if( dirPlay ) return true;
  40. if( CoCreateInstance( CLSID_DirectPlay,0,CLSCTX_ALL,IID_IDirectPlay4A,(void**)&dirPlay )>=0 ) return true;
  41. MessageBox( hwnd,"Error opening DirectPlay","DirectPlay Error",MB_ICONWARNING );
  42. return false;
  43. }
  44. static bool closeDirPlay( HWND hwnd ){
  45. if( hwnd && timer ) KillTimer( hwnd,timer );
  46. timer=0;if( !dirPlay ) return true;
  47. dirPlay->Close();
  48. int n=dirPlay->Release();
  49. dirPlay=0;return n==0;
  50. }
  51. static BOOL FAR PASCAL enumConnection( LPCGUID guid,LPVOID conn,DWORD size,LPCDPNAME name,DWORD flags,LPVOID context ){
  52. IDirectPlay4 *dp;
  53. if( CoCreateInstance( CLSID_DirectPlay,0,CLSCTX_ALL,IID_IDirectPlay4A,(void**)&dp )<0 ) return FALSE;
  54. int n=dp->InitializeConnection( conn,0 );
  55. dp->Release();if( n<0 ) return TRUE;
  56. Connection *c=d_new Connection( *guid,string( strdup( name->lpszShortNameA ) ),conn,size );
  57. connections.push_back( c );
  58. return TRUE;
  59. }
  60. static BOOL FAR PASCAL enumSession( LPCDPSESSIONDESC2 desc,LPDWORD timeout,DWORD flags,LPVOID lpContext ){
  61. if( !desc ) return FALSE;
  62. sessions.push_back( d_new Session( desc ) );
  63. return TRUE;
  64. }
  65. static bool startGame( HWND hwnd ){
  66. if( !dirPlay ) return false;
  67. char buff[MAX_PATH];
  68. int n=GetWindowText( GetDlgItem( hwnd,IDC_GAMENAME ),buff,MAX_PATH );
  69. if( !n ){
  70. MessageBox( hwnd,"Please enter a name for the new game","DirectPlay Request",MB_SETFOREGROUND|MB_TOPMOST|MB_ICONINFORMATION|MB_OK );
  71. return false;
  72. }
  73. string name=string( buff )+'\0';
  74. DPSESSIONDESC2 desc;
  75. memset(&desc,0,sizeof(desc));
  76. desc.dwSize=sizeof(desc);
  77. desc.guidApplication=GUID_NULL;
  78. desc.dwFlags=
  79. DPSESSION_KEEPALIVE|
  80. DPSESSION_MIGRATEHOST|
  81. DPSESSION_NOMESSAGEID|
  82. DPSESSION_OPTIMIZELATENCY|
  83. DPSESSION_DIRECTPLAYPROTOCOL;
  84. desc.lpszSessionNameA=(char*)name.data();
  85. if( dirPlay->Open( &desc,DPOPEN_CREATE )<0 ){
  86. MessageBox( hwnd,"Unable to create new game","DirPlay Error",MB_ICONWARNING );
  87. return false;
  88. }
  89. return true;
  90. }
  91. static bool joinGame( HWND hwnd ){
  92. if( !dirPlay ) return false;
  93. int ses=SendDlgItemMessage( hwnd,IDC_GAMELIST,LB_GETCURSEL,0,0 );
  94. if( ses<0 || ses>=sessions.size() ) return false;
  95. DPSESSIONDESC2 desc;
  96. memset(&desc,0,sizeof(desc));
  97. desc.dwSize=sizeof(desc);
  98. desc.guidInstance=sessions[ses]->guid;
  99. if( dirPlay->Open( &desc,DPOPEN_JOIN )<0 ){
  100. MessageBox( hwnd,"Unable to join game","DirPlay Error",MB_ICONWARNING );
  101. return false;
  102. }
  103. return true;
  104. }
  105. static bool enumSessions( HWND hwnd ){
  106. if( !dirPlay ) return false;
  107. clearSessions();
  108. EnableWindow( GetDlgItem( hwnd,IDC_GAMELIST ),true );
  109. SendDlgItemMessage( hwnd,IDC_GAMELIST,LB_RESETCONTENT,0,0 );
  110. DPSESSIONDESC2 desc;
  111. memset(&desc,0,sizeof(desc));
  112. desc.dwSize=sizeof(desc);
  113. desc.guidApplication=GUID_NULL;
  114. int n=dirPlay->EnumSessions( &desc,0,enumSession,0,DPENUMSESSIONS_ASYNC );
  115. if( n>=0 ){
  116. if( !timer ) SetTimer( hwnd,timer=1,1000,0 );
  117. for( int k=0;k<sessions.size();++k ){
  118. SendDlgItemMessage( hwnd,IDC_GAMELIST,LB_ADDSTRING,0,(LPARAM)strdup( sessions[k]->name.c_str() ) );
  119. }
  120. if( !sessions.size() ){
  121. SendDlgItemMessage( hwnd,IDC_GAMELIST,LB_ADDSTRING,0,(LPARAM)"<no games found>" );
  122. EnableWindow( GetDlgItem( hwnd,IDC_GAMELIST ),false );
  123. }
  124. return true;
  125. }
  126. closeDirPlay( hwnd );
  127. if( n==DPERR_USERCANCEL ) return false;
  128. MessageBox( hwnd,"Unable to enumerate sessions","DirPlay Error",MB_ICONWARNING );
  129. return false;
  130. }
  131. static bool connect( HWND hwnd ){
  132. int con=SendDlgItemMessage( hwnd,IDC_CONNECTIONS,CB_GETCURSEL,0,0 );
  133. if( con<1 || con>=connections.size() ) return false;
  134. closeDirPlay( hwnd );
  135. if( openDirPlay( hwnd ) ){
  136. int n=dirPlay->InitializeConnection( connections[con]->data,0 );
  137. if( n>=0 ){
  138. if( enumSessions( hwnd ) ) return true;
  139. }else{
  140. if( n!=DPERR_USERCANCEL ){
  141. string t="Unable to open "+connections[con]->name;
  142. MessageBox( hwnd,t.c_str(),"DirPlay Error",MB_ICONWARNING );
  143. }
  144. }
  145. closeDirPlay( hwnd );
  146. }
  147. return false;
  148. }
  149. static void endDialog( HWND hwnd,int rc ){
  150. if( timer ) KillTimer( hwnd,timer );
  151. timer=0;
  152. if( !rc ) closeDirPlay( hwnd );
  153. EndDialog( hwnd,rc );
  154. }
  155. static BOOL CALLBACK dialogProc( HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam ){
  156. int k,lo=LOWORD(wparam),hi=HIWORD(wparam);
  157. bool reset=false;
  158. switch( msg ){
  159. case WM_INITDIALOG:
  160. SetForegroundWindow( hwnd );
  161. clearConnections();
  162. connections.push_back( d_new Connection( GUID_NULL,"<no connection>","",0 ) );
  163. if( openDirPlay( hwnd ) ){
  164. if( dirPlay->EnumConnections( 0,enumConnection,0,0 )<0 ){
  165. MessageBox( hwnd,"Failed to enumerate connections","DirectPlay Error",MB_SETFOREGROUND|MB_TOPMOST|MB_ICONWARNING|MB_OK );
  166. }
  167. closeDirPlay( hwnd );
  168. }
  169. for( k=0;k<connections.size();++k ){
  170. string t=connections[k]->name;
  171. SendDlgItemMessage( hwnd,IDC_CONNECTIONS,CB_ADDSTRING,0,(LPARAM)t.c_str() );
  172. }
  173. timer=0;
  174. reset=true;
  175. break;
  176. case WM_TIMER: //refresh sessions list!
  177. if( timer && wparam==timer && !enumSessions( hwnd ) ) reset=true;
  178. break;
  179. case WM_CLOSE:
  180. endDialog( hwnd,0 );
  181. break;
  182. case WM_COMMAND:
  183. switch( hi ){
  184. case BN_CLICKED:
  185. switch( lo ){
  186. case IDC_CANCEL:
  187. endDialog( hwnd,0 );
  188. break;
  189. case IDC_GAMENAME:case IDC_HOSTGAME:
  190. if( startGame( hwnd ) ){
  191. endDialog( hwnd,2 );
  192. }
  193. break;
  194. }
  195. break;
  196. case LBN_DBLCLK:
  197. switch( lo ){
  198. case IDC_GAMELIST:
  199. if( joinGame( hwnd ) ){
  200. endDialog( hwnd,1 );
  201. }
  202. break;
  203. }
  204. break;
  205. case CBN_SELCHANGE:
  206. switch( lo ){
  207. case IDC_CONNECTIONS:
  208. if( connect( hwnd ) ){
  209. EnableWindow( GetDlgItem( hwnd,IDC_GAMENAME ),true );
  210. EnableWindow( GetDlgItem( hwnd,IDC_HOSTGAME ),true );
  211. break;
  212. }else{
  213. reset=true;
  214. }
  215. break;
  216. }
  217. break;
  218. }
  219. break;
  220. default:
  221. return 0;
  222. }
  223. if( reset ){
  224. closeDirPlay( hwnd );
  225. SendDlgItemMessage( hwnd,IDC_CONNECTIONS,CB_SETCURSEL,0,0 );
  226. EnableWindow( GetDlgItem( hwnd,IDC_GAMELIST ),false );
  227. EnableWindow( GetDlgItem( hwnd,IDC_HOSTGAME ),false );
  228. EnableWindow( GetDlgItem( hwnd,IDC_GAMENAME ),false );
  229. SetWindowText( GetDlgItem( hwnd,IDC_GAMENAME ),"" );
  230. SendDlgItemMessage( hwnd,IDC_GAMELIST,LB_RESETCONTENT,0,0 );
  231. }
  232. return 1;
  233. }
  234. void multiplay_setup_create(){
  235. dirPlay=0;
  236. }
  237. void multiplay_setup_destroy(){
  238. multiplay_setup_close();
  239. }
  240. int multiplay_setup_open(){
  241. gx_runtime->idle();
  242. int n=DialogBox( GetModuleHandle( "runtime" ),MAKEINTRESOURCE( IDD_MULTIPLAYER ),GetDesktopWindow(),dialogProc );
  243. if( n!=1 && n!=2 ) n=0;
  244. clearSessions();
  245. clearConnections();
  246. //NAUGHTY!
  247. gx_runtime->asyncRun();
  248. gx_runtime->idle();
  249. return n;
  250. }
  251. void multiplay_setup_close(){
  252. closeDirPlay( 0 );
  253. }
  254. int multiplay_setup_host( const string &game_name ){
  255. int ret=0;
  256. IDirectPlayLobby *lobby;
  257. IDirectPlayLobby3 *lobby3;
  258. if( CoCreateInstance( CLSID_DirectPlay,0,CLSCTX_ALL,IID_IDirectPlay4A,(void**)&dirPlay )>=0 ){
  259. if( DirectPlayLobbyCreate( 0,&lobby,0,0,0 )>=0 ){
  260. if( lobby->QueryInterface( IID_IDirectPlayLobby3,(void**)&lobby3 )>=0 ){
  261. //ok, create an address for initializeconnection
  262. string ip( "\0" );
  263. char address[256];DWORD sz=256;
  264. if( lobby3->CreateAddress( DPSPGUID_TCPIP,DPAID_INet,ip.data(),ip.size(),address,&sz )>=0 ){
  265. if( dirPlay->InitializeConnection( address,0 )>=0 ){
  266. string name=game_name+'\0';
  267. DPSESSIONDESC2 desc;
  268. memset(&desc,0,sizeof(desc));
  269. desc.dwSize=sizeof(desc);
  270. desc.guidApplication=GUID_NULL;
  271. desc.dwFlags=
  272. DPSESSION_KEEPALIVE|
  273. DPSESSION_MIGRATEHOST|
  274. DPSESSION_NOMESSAGEID|
  275. DPSESSION_OPTIMIZELATENCY|
  276. DPSESSION_DIRECTPLAYPROTOCOL;
  277. desc.lpszSessionNameA=(char*)name.data();
  278. if( dirPlay->Open( &desc,DPOPEN_CREATE )>=0 ){
  279. ret=2;
  280. }
  281. }
  282. }
  283. lobby3->Release();
  284. }
  285. lobby->Release();
  286. }
  287. if( !ret ){
  288. dirPlay->Release();
  289. dirPlay=0;
  290. }
  291. }
  292. return ret;
  293. }
  294. int multiplay_setup_join( const string &game_name,const string &ip_add ){
  295. int ret=0;
  296. IDirectPlayLobby *lobby;
  297. IDirectPlayLobby3 *lobby3;
  298. if( CoCreateInstance( CLSID_DirectPlay,0,CLSCTX_ALL,IID_IDirectPlay4A,(void**)&dirPlay )>=0 ){
  299. if( DirectPlayLobbyCreate( 0,&lobby,0,0,0 )>=0 ){
  300. if( lobby->QueryInterface( IID_IDirectPlayLobby3,(void**)&lobby3 )>=0 ){
  301. //ok, create an address for initializeconnection
  302. string ip=ip_add+'\0';
  303. char address[256];DWORD sz=256;
  304. if( lobby3->CreateAddress( DPSPGUID_TCPIP,DPAID_INet,ip.data(),ip.size(),address,&sz )>=0 ){
  305. if( dirPlay->InitializeConnection( address,0 )>=0 ){
  306. DPSESSIONDESC2 desc;
  307. memset(&desc,0,sizeof(desc));
  308. desc.dwSize=sizeof(desc);
  309. desc.guidApplication=GUID_NULL;
  310. if( dirPlay->EnumSessions( &desc,0,enumSession,0,0 )>=0 ){
  311. for( int k=0;k<sessions.size();++k ){
  312. if( sessions[k]->name!=game_name ) continue;
  313. desc.guidInstance=sessions[k]->guid;
  314. if( dirPlay->Open( &desc,DPOPEN_JOIN )>=0 ){
  315. ret=1;
  316. }
  317. break;
  318. }
  319. }
  320. clearSessions();
  321. }
  322. }
  323. lobby3->Release();
  324. }
  325. lobby->Release();
  326. }
  327. if( !ret ){
  328. dirPlay->Release();
  329. dirPlay=0;
  330. }
  331. }
  332. return ret;
  333. }