home *** CD-ROM | disk | FTP | other *** search
/ WarCraft 2000 - Nuclear Epidemic / W2000.nrg / SOURCE.War2000 / MPlayer.cpp < prev    next >
C/C++ Source or Header  |  1998-09-25  |  29KB  |  1,117 lines

  1. //MULTIPLAYER
  2. #define INITGUID
  3. #include "ddini.h"
  4. #include "ResFile.h"
  5. #include "FastDraw.h"
  6. #include "mgraph.h"
  7. #include "mouse.h"
  8. #include "menu.h"
  9. #include "MapDiscr.h"
  10. #include "dpchat.h"
  11. #include "dplobby.h"
  12. #include "fonts.h"
  13. #include "dialogs.h"
  14. extern RLCFont FPassive;
  15. extern RLCFont FActive;
  16. extern RLCFont FDisable;
  17. extern DWORD Signatur[2049];
  18. Menu SingleMulti;
  19. Menu ChooseConn;
  20. Menu ChooseSession;
  21. Menu StartMultiplayer;
  22. word PlayerMenuMode;
  23. word PrevRpos;
  24. extern int COUNTER;
  25. bool ProcessMessages();
  26. int WaitCycle;
  27. bool NetworkGame;
  28. bool GameInProgress;
  29. LPDIRECTPLAY3A        lpDirectPlay3A;
  30. static LPDPLAYINFO        lpDPInfo;
  31. const DWORD APPMSG_CHATSTRING    = 0;            // message type for chat string
  32. const DWORD MAXNAMELEN        = 200;        // max size of a session or player name
  33. char                    szSessionName[MAXNAMELEN];
  34. char                    szPlayerName[MAXNAMELEN];
  35. const DWORD ExDataID=0xF376425E;
  36. const DWORD PlExitID=0xEA3521BC;
  37. const DWORD NON=0xFFFFFFFF;
  38. //data transferring format
  39. // int ExDataID
  40. // int Time 
  41. // int Rand_Index
  42. // data
  43. extern int tmtmt;
  44. word NProviders;
  45. word NPlayers;
  46. word NSessions;
  47. DWORD RealTime;
  48. LPVOID lplpConnectionBuffer[16];
  49. GUID SessionsGUID[32];
  50. DPID PlayersID[32];
  51. byte* PData[32];
  52. DWORD PDSize[32];
  53. bool PUsed[32];
  54. bool Ready;
  55. extern byte ExBuf[8192];
  56. extern byte MyRace;
  57. extern char CurrentMap[64];
  58. extern int EBPos;
  59. DPID MyDPID;
  60. DPID ServerDPID;
  61. DWORD MyDSize;
  62. byte* MyData;
  63. char ProvidersList [512];
  64. char PlayersList[512];
  65. char SessionsList[512];
  66. bool CreateMultiplaterInterface();
  67. DWORD ExBuf1[2193];
  68. DWORD EBPos1;
  69. int PLNAT[8];
  70. void PrepareGameMedia(byte myid);
  71. // message structure used to send a chat string to another player
  72. typedef struct {
  73.     DWORD    dwType;                                // message type (APPMSG_CHATSTRING)
  74.     char    szMsg[1];                            // message string (variable length)
  75. } MSG_CHATSTRING, *LPMSG_CHATSTRING;
  76. void IAmLeft();
  77. HRESULT ShutdownConnection(LPDPLAYINFO lpDPInfo);
  78. // globals
  79. HANDLE            ghReceiveThread = NULL;            // handle of receive thread
  80. DWORD            gidReceiveThread = 0;            // id of receive thread
  81. HANDLE            ghKillReceiveEvent = NULL;        // event used to kill receive thread
  82. HWND            ghChatWnd = NULL;                // main chat window
  83. DPLAYINFO    DPInfo;
  84. //execute bufferisation
  85. #define MaxPL 8
  86. struct EXBUFFER{
  87.     DWORD Size;
  88.     bool Enabled;
  89.     DWORD Sign;//0xF376425E
  90.     DWORD RealTime;//if(??==0xFFFFFFFF)-empty buffer
  91.     DWORD RandIndex;
  92.     byte  Data[2048];
  93. };
  94. EXBUFFER EBufs[MaxPL];
  95. EXBUFFER EBufs1[MaxPL];
  96. //network errors:
  97. int SeqErrorsCount;
  98. int LastRandDif;
  99. void SetupEBufs(){
  100.     SeqErrorsCount=0;
  101.     LastRandDif=0;
  102.     PrevRpos=0;
  103.     for(int i=0;i<MaxPL;i++){
  104.         EBufs[i].RealTime=NON;
  105.         EBufs1[i].RealTime=NON;
  106.         EBufs[i].Enabled=true;
  107.         EBufs1[i].Enabled=true;
  108.         EBufs[i].Size=0;
  109.         EBufs1[i].Size=0;
  110.     };
  111. };
  112. extern word rpos;
  113. void UpdateEBufs(){
  114.     //copy containig to ExBuf
  115.     byte* EPOS=ExBuf;
  116.     EBPos=0;
  117.     word FirstRand=0xFFFF;
  118.     word OtherRand=0xFFFF;
  119.     for(int i=0;i<MaxPL;i++){
  120.         //checking random sequence
  121.         if(EBufs[i].RealTime!=NON){
  122.             if(FirstRand==0xFFFF){
  123.                 FirstRand=word(EBufs[i].RandIndex);
  124.             }else{
  125.                 if(EBufs[i].RandIndex!=FirstRand){
  126.                     SeqErrorsCount++;
  127.                     LastRandDif=int(EBufs[i].RandIndex)-int(FirstRand);
  128.                     rpos=FirstRand;
  129.                 };
  130.             };
  131.             //copy data to execute buffer
  132.             memcpy(EPOS,&EBufs[i].Data,EBufs[i].Size);
  133.             EPOS+=EBufs[i].Size;
  134.             EBPos+=EBufs[i].Size;
  135.         };
  136.         EBufs[i].RealTime=EBufs1[i].RealTime;
  137.         if(EBufs1[i].RealTime!=NON){
  138.             memcpy(&EBufs[i].Data,&EBufs1[i].Data,
  139.                 EBufs1[i].Size);
  140.             EBufs[i].Size=EBufs1[i].Size;
  141.             EBufs[i].RandIndex=EBufs1[i].RandIndex;
  142.             EBufs1[i].Size=0;
  143.             EBufs1[i].RealTime=NON;
  144.         };
  145.     };
  146. };
  147. bool PresentEmptyBuf(){
  148.     bool zzz=false;
  149.     for(int i=0;i<NPlayers;i++)
  150.         if(EBufs[i].RealTime==NON&&EBufs[i].Enabled)zzz=true;
  151.     return zzz;
  152. };
  153. BOOL WINAPI EnumPlayersCallback2(DPID dpId,
  154.     DWORD dwPlayerType, LPCDPNAME lpName,
  155.     DWORD dwFlags, LPVOID lpContext){
  156.     PlayersID[NPlayers]=dpId;
  157.     strcat(PlayersList,lpName->lpszShortNameA);
  158.     strcat(PlayersList,"|");
  159.     NPlayers++;
  160.     return true;
  161. };
  162. void EnumeratePlayers(){
  163.     NPlayers=0;
  164.     PlayersList[0]=0;
  165.     strcat(PlayersList,"═└╫└╥▄ ╚├╨╙|┬█╒╬─| |");
  166.     if(int(lpDirectPlay3A)){
  167.         lpDirectPlay3A->EnumPlayers((GUID*)&DPCHAT_GUID,
  168.             EnumPlayersCallback2,NULL,0);
  169.     };
  170.     StartMultiplayer.CreateMenu(PlayersList,
  171.         &f32x32w,&f32x32g,NULL,MCP_MAKESHIFT|MCP_CHANGEFONT);
  172. };
  173. InputBox** IBBX;
  174. BOOL WINAPI IBEnumPlayersCallback2(DPID dpId,
  175.     DWORD dwPlayerType, LPCDPNAME lpName,
  176.     DWORD dwFlags, LPVOID lpContext){
  177.     PlayersID[NPlayers]=dpId;
  178.     strcpy(IBBX[NPlayers]->Str,lpName->lpszShortNameA);
  179.     NPlayers++;
  180.     return true;
  181. };
  182. void IBEnumeratePlayers(InputBox** IB){
  183.     for(int i=0;i<8;i++)IB[i]->Str[0]=0;
  184.     IBBX=IB;
  185.     NPlayers=0;
  186.     PlayersList[0]=0;
  187.     strcat(PlayersList,"═└╫└╥▄ ╚├╨╙|┬█╒╬─| |");
  188.     if(int(lpDirectPlay3A)){
  189.         lpDirectPlay3A->EnumPlayers((GUID*)&DPCHAT_GUID,
  190.             IBEnumPlayersCallback2,NULL,0);
  191.     };
  192.     StartMultiplayer.CreateMenu(PlayersList,
  193.         &f32x32w,&f32x32g,NULL,MCP_MAKESHIFT|MCP_CHANGEFONT);
  194. };
  195. int GetPIndex(DPID PD){
  196.     int i=0;
  197.     while(i<NPlayers&&PD!=PlayersID[i])i++;
  198.     if(i<NPlayers)return i;
  199.     else return -1;
  200. };
  201. void HandleApplicationMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  202.                               DPID idFrom, DPID idTo)
  203. {
  204.     DWORD SDP=idTo==DPID_ALLPLAYERS?MyDPID:idTo;
  205.         if(SDP==MyDPID){
  206.             int ii=GetPIndex(idFrom);
  207.             if(ii<0)return;
  208.             DWORD*   lp =(DWORD*) (LPMSG_CHATSTRING) lpMsg;
  209.             if(lp[0]==ExDataID&&dwMsgSize<2048){
  210.                 if(lp[1]==RealTime){
  211.                     EBufs[ii].Size=dwMsgSize-12;
  212.                     EBufs[ii].RandIndex=lp[2];
  213.                     memcpy(&EBufs[ii].Data,&lp[3],dwMsgSize-12);
  214.                     EBufs[ii].RealTime=RealTime;
  215.                 };
  216.                 if(lp[1]==RealTime+1){
  217.                     EBufs1[ii].Size=dwMsgSize-12;
  218.                     EBufs1[ii].RandIndex=lp[2];
  219.                     memcpy(&EBufs1[ii].Data,&lp[3],dwMsgSize-12);
  220.                     EBufs1[ii].RealTime=RealTime+1;
  221.                 };
  222.             }else{
  223.                 if(lp[0]==PlExitID){
  224.                     EBufs[ii].Enabled=false;
  225.                     sprintf(Prompt,"╚π≡εΩ %s Γ√°σδ Φτ Φπ≡√.",StartMultiplayer.GetNstr(3+ii));
  226.                     PromptTime=400;
  227.                 };
  228.                 if(MyData)free(MyData);
  229.                 MyData=new byte[dwMsgSize];
  230.                 memcpy(MyData,lp,dwMsgSize);
  231.                 
  232.             };
  233.         };
  234. };
  235.  
  236. void HandleSystemMessage(LPDPLAYINFO lpDPInfo, LPDPMSG_GENERIC lpMsg, DWORD dwMsgSize,
  237.                          DPID idFrom, DPID idTo)
  238. {
  239.     LPSTR        lpszStr = NULL;
  240.  
  241.     // The body of each case is there so you can set a breakpoint and examine
  242.     // the contents of the message received.
  243.     switch (lpMsg->dwType)
  244.     {
  245.     case DPSYS_CREATEPLAYERORGROUP:
  246.         {
  247.             LPDPMSG_CREATEPLAYERORGROUP        lp = (LPDPMSG_CREATEPLAYERORGROUP) lpMsg;
  248.             LPSTR                            lpszPlayerName;
  249.             LPSTR                            szDisplayFormat = "\"%s\" has joined\r\n";
  250.             
  251.             // get pointer to player name
  252.             if (lp->dpnName.lpszShortNameA)
  253.                 lpszPlayerName = lp->dpnName.lpszShortNameA;
  254.             else
  255.                 lpszPlayerName = "unknown";
  256.  
  257.             // allocate space for string
  258.             lpszStr = new char[lstrlen(szDisplayFormat) +
  259.                                                    lstrlen(lpszPlayerName) + 1];
  260.             if (lpszStr == NULL)
  261.                 break;
  262.  
  263.             // build string
  264.             wsprintf(lpszStr, szDisplayFormat, lpszPlayerName);
  265.         }
  266.         break;
  267.  
  268.     case DPSYS_DESTROYPLAYERORGROUP:
  269.         {
  270.             LPDPMSG_DESTROYPLAYERORGROUP    lp = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
  271.             LPSTR                            lpszPlayerName;
  272.             LPSTR                            szDisplayFormat = "\"%s\" has left\r\n";
  273.             
  274.             // get pointer to player name
  275.             if (lp->dpnName.lpszShortNameA)
  276.                 lpszPlayerName = lp->dpnName.lpszShortNameA;
  277.             else
  278.                 lpszPlayerName = "unknown";
  279.  
  280.             // allocate space for string
  281.             lpszStr = new char[lstrlen(szDisplayFormat) +
  282.                                                    lstrlen(lpszPlayerName) + 1];
  283.             if (lpszStr == NULL)
  284.                 break;
  285.  
  286.             // build string
  287.             wsprintf(lpszStr, szDisplayFormat, lpszPlayerName);
  288.         }
  289.         break;
  290.  
  291.     case DPSYS_ADDPLAYERTOGROUP:
  292.         {
  293.             LPDPMSG_ADDPLAYERTOGROUP lp = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
  294.         }
  295.         break;
  296.  
  297.     case DPSYS_DELETEPLAYERFROMGROUP:
  298.         {
  299.             LPDPMSG_DELETEPLAYERFROMGROUP lp = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
  300.         }
  301.         break;
  302.  
  303.     case DPSYS_SESSIONLOST:
  304.         {
  305.             LPDPMSG_SESSIONLOST lp = (LPDPMSG_SESSIONLOST)lpMsg;
  306.         }
  307.         break;
  308.  
  309.     case DPSYS_HOST:
  310.         {
  311.             LPDPMSG_HOST    lp = (LPDPMSG_HOST)lpMsg;
  312.             LPSTR            szDisplayFormat = "You have become the host\r\n";
  313.  
  314.             // allocate space for string
  315.             lpszStr = new char[strlen(szDisplayFormat) + 1];
  316.             if (lpszStr == NULL)
  317.                 break;
  318.  
  319.             // build string
  320.             lstrcpy(lpszStr, szDisplayFormat);
  321.  
  322.             // we are now the host
  323.             lpDPInfo->bIsHost = TRUE;
  324.         }
  325.         break;
  326.  
  327.     case DPSYS_SETPLAYERORGROUPDATA:
  328.         {
  329.             LPDPMSG_SETPLAYERORGROUPDATA lp = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
  330.         }
  331.         break;
  332.  
  333.     case DPSYS_SETPLAYERORGROUPNAME:
  334.         {
  335.             LPDPMSG_SETPLAYERORGROUPNAME lp = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
  336.         }
  337.         break;
  338.     }
  339.  
  340.     // post string to chat window
  341.     if (lpszStr)
  342.     {
  343.         // make sure window is still valid
  344.         //if (ghChatWnd)
  345.         //    PostMessage(ghChatWnd, WM_USER_ADDSTRING, (WPARAM) 0, (LPARAM) lpszStr);
  346.         //else
  347.         free(lpszStr);
  348.     }
  349. }
  350. HRESULT ReceiveMessage(LPDPLAYINFO lpDPInfo){
  351.     DPID                idFrom, idTo;
  352.     LPVOID                lpvMsgBuffer;
  353.     DWORD                dwMsgBufferSize;
  354.     HRESULT                hr;
  355.  
  356.     lpvMsgBuffer = NULL;
  357.     dwMsgBufferSize = 0;
  358.  
  359.     // loop to read all messages in queue
  360.     //do
  361.     //{
  362.         // loop until a single message is successfully read
  363.         do
  364.         {
  365.             // read messages from any player, including system player
  366.             idFrom = 0;
  367.             idTo = 0;
  368.  
  369.             hr = lpDPInfo->lpDirectPlay3A->Receive(&idFrom, &idTo, DPRECEIVE_ALL,
  370.                                                    lpvMsgBuffer, &dwMsgBufferSize);
  371.  
  372.             // not enough room, so resize buffer
  373.             if (hr == DPERR_BUFFERTOOSMALL)
  374.             {
  375.                 if (lpvMsgBuffer)
  376.                     free(lpvMsgBuffer);
  377.                 lpvMsgBuffer = new byte[dwMsgBufferSize];
  378.                 if (lpvMsgBuffer == NULL)
  379.                     hr = DPERR_OUTOFMEMORY;
  380.             }
  381.         } while (hr == DPERR_BUFFERTOOSMALL);
  382.  
  383.         if ((SUCCEEDED(hr)) &&                            // successfully read a message
  384.             (dwMsgBufferSize >= sizeof(DPMSG_GENERIC)))    // and it is big enough
  385.         {
  386.             // check for system message
  387.             if (idFrom == DPID_SYSMSG)
  388.             {
  389. //                HandleSystemMessage(lpDPInfo, (LPDPMSG_GENERIC) lpvMsgBuffer,
  390. //                                    dwMsgBufferSize, idFrom, idTo);
  391.             }
  392.             else
  393.             {
  394.                 HandleApplicationMessage(lpDPInfo, (LPDPMSG_GENERIC) lpvMsgBuffer,
  395.                                          dwMsgBufferSize, idFrom, idTo);
  396.             }
  397.         }
  398.     //} while (SUCCEEDED(hr));
  399.  
  400.     // free any memory we created
  401.     if (lpvMsgBuffer)
  402.         free(lpvMsgBuffer);
  403.  
  404.     return (DP_OK);
  405.  
  406.     return 0;
  407. };
  408.  
  409. HRESULT SetupConnection(HINSTANCE hInstance, LPDPLAYINFO lpDPInfo)
  410. {
  411.     HRESULT        hr;
  412.  
  413.     ZeroMemory(lpDPInfo, sizeof(DPLAYINFO));
  414.     ZeroMemory(PData,sizeof(PData));
  415.     ZeroMemory(PlayersID,sizeof(PlayersID));
  416.     ZeroMemory(&MyData,sizeof(4*32));
  417.     NPlayers=0;
  418.     ServerDPID=0xFFFFFFFF;
  419.     MyDPID=0;
  420.     GameInProgress=false;
  421.     // create event used by DirectPlay to signal a message has arrived
  422.         return (DP_OK);    
  423.  
  424.     
  425.     return (hr);
  426. }
  427. void SetupMultiplayer(HINSTANCE hInstance){
  428.     SetupConnection(hInstance,&DPInfo);
  429.     lpDPInfo=&DPInfo;
  430. };
  431. void ShutdownMultiplayer(){
  432.     IAmLeft();
  433.     ShutdownConnection(lpDPInfo);
  434. };
  435. HRESULT ShutdownConnection(LPDPLAYINFO lpDPInfo)
  436. {
  437.     
  438.  
  439.     if (lpDPInfo->lpDirectPlay3A)
  440.     {
  441.         if (lpDPInfo->dpidPlayer)
  442.         {
  443.             lpDPInfo->lpDirectPlay3A->DestroyPlayer(lpDPInfo->dpidPlayer);
  444.             lpDPInfo->dpidPlayer = 0;
  445.         }
  446.         lpDPInfo->lpDirectPlay3A->Close();
  447.         lpDPInfo->lpDirectPlay3A->Release();
  448.         lpDPInfo->lpDirectPlay3A = NULL;
  449.     }
  450.  
  451.     
  452.     return (DP_OK);
  453. }
  454.  
  455. void InitMultiDialogs(){
  456.     //SingleMulti.CreateMenu("╬─╚═╬╫═└▀ ╚├╨└|╚├╨└ ╧╬ ╤┼╥╚|┬█╒╬─",
  457.     //    &f32x32g,&f32x32r,NULL,MCP_MAKESHIFT|MCP_CHANGEFONT);
  458.     //StartMultiplayer.CreateMenu("═└╫└╥▄ ╚├╨╙|┬█╒╬─",
  459.     //    &f32x32g,&f32x32r,NULL,MCP_MAKESHIFT|MCP_CHANGEFONT);
  460.     NetworkGame=false;
  461.     lpDirectPlay3A = NULL;
  462.     NProviders=0;
  463.     CreateMultiplaterInterface();
  464.     //strcat(ProvidersList,"╧≡σΣ√Σ≤∙σσ ∞σφ■");
  465.     //ChooseConn.CreateMenu(ProvidersList,
  466.     //    &f16x16w,&f16x16r,NULL,MCP_MAKESHIFT|MCP_CHANGEFONT);
  467.     PlayerMenuMode=1;
  468.     NPlayers=0;
  469.     GameInProgress=false;
  470. };
  471.  
  472. HRESULT CreateDirectPlayInterface( LPDIRECTPLAY3A *lplpDirectPlay3A )
  473. {
  474.     HRESULT                hr;
  475.     LPDIRECTPLAY3A        lpDirectPlay3A = NULL;
  476.     hr = CoInitialize(NULL);
  477.     // Create an IDirectPlay3 interface
  478.     hr = CoCreateInstance(    CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, 
  479.                             IID_IDirectPlay3A, (LPVOID*)&lpDirectPlay3A);
  480.  
  481.     // return interface created
  482.     *lplpDirectPlay3A = lpDirectPlay3A;
  483.  
  484.     return (hr);
  485. };
  486. /*HRESULT DestroyDirectPlayInterface(HWND hWnd, LPDIRECTPLAY3A lpDirectPlay3A)
  487. {
  488.     HRESULT        hr = DP_OK;
  489.  
  490.     if (lpDirectPlay3A)
  491.     {
  492.         DeleteSessionInstanceList(hWnd);
  493.         EnableDlgButton(hWnd, IDC_JOINBUTTON, FALSE);
  494.  
  495.         hr = lpDirectPlay3A->Release();
  496.     }
  497.  
  498.     return (hr);
  499. };*/
  500. BOOL FAR PASCAL DirectPlayEnumConnectionsCallback(
  501.                         LPCGUID     lpguidSP,
  502.                         LPVOID        lpConnection,
  503.                         DWORD        dwConnectionSize,
  504.                         LPCDPNAME   lpName,
  505.                         DWORD         dwFlags,
  506.                         LPVOID         lpContext)
  507. {
  508.  
  509.     HWND            hWnd = (HWND) lpContext;
  510.  
  511.     // store service provider name in list
  512.     strcat(ProvidersList,lpName->lpszShortNameA);
  513.     strcat(ProvidersList,"|");
  514.     // make space for connection shortcut
  515.     lplpConnectionBuffer[NProviders] = new byte[dwConnectionSize];
  516.     if (lplpConnectionBuffer[NProviders] == NULL)
  517.         goto FAILURE;
  518.  
  519.     // store pointer to connection shortcut in list
  520.     memcpy(lplpConnectionBuffer[NProviders], lpConnection, dwConnectionSize);
  521.     NProviders++;
  522.  
  523. FAILURE:
  524.     return (TRUE);
  525. };
  526. bool CreateMultiplaterInterface(){
  527.     if FAILED(CreateDirectPlayInterface(&lpDirectPlay3A)) return false;
  528.     if(NProviders>0){
  529.         for(int i=0;i<NProviders;i++)free(lplpConnectionBuffer[i]);
  530.     };
  531.     ProvidersList[0]=0;
  532.     NProviders=0;
  533.     lpDirectPlay3A->EnumConnections(&DPCHAT_GUID,
  534.         DirectPlayEnumConnectionsCallback,hwnd,0);
  535.     return true;
  536. };
  537. BOOL FAR PASCAL EnumSessionsCallback(
  538.                         LPCDPSESSIONDESC2    lpSessionDesc,
  539.                         LPDWORD                lpdwTimeOut,
  540.                         DWORD                dwFlags,
  541.                         LPVOID                lpContext)
  542. {
  543.     HWND            hWnd = (HWND) lpContext;
  544.  
  545.     // see if last session has been enumerated
  546.     if (dwFlags & DPESC_TIMEDOUT)
  547.         return (FALSE);                        
  548.  
  549.     // store session name in list
  550.     strcat(SessionsList,lpSessionDesc->lpszSessionNameA);
  551.     strcat(SessionsList,"|");
  552.     SessionsGUID[NSessions]=lpSessionDesc->guidInstance;
  553.     NSessions++;
  554.     return (TRUE);
  555. }
  556. void EnumerateSessions(){
  557.     DPSESSIONDESC2        sessionDesc;
  558.     PlayersList[0]=0;
  559.     NPlayers=0;
  560.     SessionsList[0]=0;
  561.     NSessions=0;
  562.     // add sessions to session list
  563.     ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
  564.     sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
  565.     sessionDesc.guidApplication = DPCHAT_GUID;
  566.     // start enumerating the sessions
  567.     lpDirectPlay3A->EnumSessions(&sessionDesc,0,
  568.         EnumSessionsCallback,hwnd,
  569.         DPENUMSESSIONS_AVAILABLE);
  570.     strcat(SessionsList,"| |╤╬╟─└╥▄ ╤┬╬▐ ╚├╨╙|╧╨┼─█─╙┘┼┼ ╠┼═▐");
  571.     ChooseSession.CreateMenu(SessionsList,
  572.         &f32x32w,&f32x32g,NULL,MCP_MAKESHIFT|MCP_CHANGEFONT);
  573. };
  574. ListBox* LBBX;
  575. BOOL FAR PASCAL LBEnumSessionsCallback(
  576.                         LPCDPSESSIONDESC2    lpSessionDesc,
  577.                         LPDWORD                lpdwTimeOut,
  578.                         DWORD                dwFlags,
  579.                         LPVOID                lpContext)
  580. {
  581.     HWND            hWnd = (HWND) lpContext;
  582.  
  583.     // see if last session has been enumerated
  584.     if (dwFlags & DPESC_TIMEDOUT)
  585.         return (FALSE);                        
  586.  
  587.     // store session name in list
  588.     LBBX->AddItem(lpSessionDesc->lpszSessionNameA,0);
  589.     SessionsGUID[NSessions]=lpSessionDesc->guidInstance;
  590.     NSessions++;
  591.     return (TRUE);
  592. }
  593. void LBEnumerateSessions(ListBox* LB){
  594.     LBBX=LB;
  595.     LB->ClearItems();
  596.     DPSESSIONDESC2        sessionDesc;
  597.     PlayersList[0]=0;
  598.     NPlayers=0;
  599.     SessionsList[0]=0;
  600.     NSessions=0;
  601.     // add sessions to session list
  602.     ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
  603.     sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
  604.     sessionDesc.guidApplication = DPCHAT_GUID;
  605.     // start enumerating the sessions
  606.     lpDirectPlay3A->EnumSessions(&sessionDesc,0,
  607.         LBEnumSessionsCallback,hwnd,
  608.         DPENUMSESSIONS_AVAILABLE);
  609. };
  610. HRESULT HostSession(LPDIRECTPLAY3A lpDirectPlay3A,
  611.                     LPSTR lpszSessionName, LPSTR lpszPlayerName,
  612.                     LPDPLAYINFO lpDPInfo)
  613. {
  614.     DPID                dpidPlayer;
  615.     DPNAME                dpName;
  616.     DPSESSIONDESC2        sessionDesc;
  617.     HRESULT                hr;
  618.  
  619.     // check for valid interface
  620.     if (lpDirectPlay3A == NULL)
  621.         return (DPERR_INVALIDOBJECT);
  622.  
  623.     // host a new session
  624.     ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
  625.     sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
  626.     sessionDesc.dwFlags = DPSESSION_MIGRATEHOST | DPSESSION_KEEPALIVE;
  627.     sessionDesc.guidApplication = DPCHAT_GUID;
  628.     sessionDesc.dwMaxPlayers = MAXPLAYERS;
  629.     sessionDesc.lpszSessionNameA = lpszSessionName;
  630.  
  631.     hr = lpDirectPlay3A->Open(&sessionDesc, DPOPEN_CREATE);
  632.     if FAILED(hr)
  633.         goto OPEN_FAILURE;
  634.  
  635.     // fill out name structure
  636.     ZeroMemory(&dpName, sizeof(DPNAME));
  637.     dpName.dwSize = sizeof(DPNAME);
  638.     dpName.lpszShortNameA = lpszPlayerName;
  639.     dpName.lpszLongNameA = NULL;
  640.  
  641.     // create a player with this name
  642.     hr = lpDirectPlay3A->CreatePlayer(&dpidPlayer, &dpName, 
  643.                             lpDPInfo->hPlayerEvent, NULL, 0, 0);
  644.     if FAILED(hr)
  645.         goto CREATEPLAYER_FAILURE;
  646.     MyDPID=dpidPlayer;
  647.     // return connection info
  648.     lpDPInfo->lpDirectPlay3A = lpDirectPlay3A;
  649.     lpDPInfo->dpidPlayer = dpidPlayer;
  650.     lpDPInfo->bIsHost = TRUE;
  651.  
  652.     return (DP_OK);
  653.  
  654. CREATEPLAYER_FAILURE:
  655. OPEN_FAILURE:
  656.     lpDirectPlay3A->Close();
  657.     return (hr);
  658. }
  659. HRESULT JoinSession(LPDIRECTPLAY3A lpDirectPlay3A,
  660.                     LPGUID lpguidSessionInstance, LPSTR lpszPlayerName,
  661.                     LPDPLAYINFO lpDPInfo)
  662. {
  663.     DPID                dpidPlayer;
  664.     DPNAME                dpName;
  665.     DPSESSIONDESC2        sessionDesc;
  666.     HRESULT                hr;
  667.  
  668.     // check for valid interface
  669.     if (lpDirectPlay3A == NULL)
  670.         return (DPERR_INVALIDOBJECT);
  671.  
  672.     // join existing session
  673.     ZeroMemory(&sessionDesc, sizeof(DPSESSIONDESC2));
  674.     sessionDesc.dwSize = sizeof(DPSESSIONDESC2);
  675.     sessionDesc.guidInstance = *lpguidSessionInstance;
  676.  
  677.     hr = lpDirectPlay3A->Open(&sessionDesc, DPOPEN_JOIN);
  678.     if FAILED(hr)
  679.         goto OPEN_FAILURE;
  680.  
  681.     // fill out name structure
  682.     ZeroMemory(&dpName, sizeof(DPNAME));
  683.     dpName.dwSize = sizeof(DPNAME);
  684.     dpName.lpszShortNameA = lpszPlayerName;
  685.     dpName.lpszLongNameA = NULL;
  686.  
  687.     // create a player with this name
  688.     hr = lpDirectPlay3A->CreatePlayer(&dpidPlayer, &dpName, 
  689.                             lpDPInfo->hPlayerEvent, NULL, 0, 0);
  690.     if FAILED(hr)
  691.         goto CREATEPLAYER_FAILURE;
  692.  
  693.     // return connection info
  694.     MyDPID=dpidPlayer;
  695.     lpDPInfo->lpDirectPlay3A = lpDirectPlay3A;
  696.     lpDPInfo->dpidPlayer = dpidPlayer;
  697.     lpDPInfo->bIsHost = FALSE;
  698.  
  699.     return (DP_OK);
  700.  
  701. CREATEPLAYER_FAILURE:
  702. OPEN_FAILURE:
  703.     lpDirectPlay3A->Close();
  704.     return (hr);
  705. };
  706. bool CreateNamedSession(char* Name){
  707.     // use computer name for session name
  708.     DWORD dwNameSize = MAXNAMELEN;
  709.     if (!GetComputerName(szSessionName, &dwNameSize))
  710.     lstrcpy(szSessionName, "Session");
  711.     // host a new session on this service provider
  712.     HRESULT hr = HostSession(lpDirectPlay3A, szSessionName, Name, lpDPInfo);
  713.     if FAILED(hr)return false;
  714.         else return true;
  715. };
  716. bool CreateSession(){
  717.     // use computer name for session name
  718.     DWORD dwNameSize = MAXNAMELEN;
  719.     if (!GetComputerName(szSessionName, &dwNameSize))
  720.     lstrcpy(szSessionName, "Session");
  721.     // use user name for player name
  722.     dwNameSize = MAXNAMELEN;
  723.     if (!GetUserName(szPlayerName, &dwNameSize))
  724.     lstrcpy(szPlayerName, "unknown");
  725.     // host a new session on this service provider
  726.     HRESULT hr = HostSession(lpDirectPlay3A, szSessionName, szPlayerName, lpDPInfo);
  727.     if FAILED(hr)return false;
  728.         else return true;
  729. };
  730. bool JoinNameToSession(int ns,char* Name){
  731.     DWORD dwNameSize;
  732.     EnumerateSessions();
  733.     if(ns>=NSessions)return false;
  734.     if FAILED(JoinSession(lpDirectPlay3A,
  735.                 &SessionsGUID[ns],Name,
  736.                 lpDPInfo))return false;
  737.     else return true;
  738. };
  739. bool JoinToSession(int ns){
  740.     DWORD dwNameSize;
  741.     EnumerateSessions();
  742.     if(ns>=NSessions)return false;
  743.     // use user name for player name
  744.     dwNameSize = MAXNAMELEN;
  745.     if (!GetUserName(szPlayerName, &dwNameSize))
  746.     lstrcpy(szPlayerName, "unknown");
  747.     if FAILED(JoinSession(lpDirectPlay3A,
  748.                 &SessionsGUID[ns],szPlayerName,
  749.                 lpDPInfo))return false;
  750.     else return true;
  751. };
  752. bool SendToAllPlayers(DWORD Size,LPVOID lpData){
  753.     if(!int(lpDirectPlay3A)||NPlayers<2)return false;
  754.     int count=0;
  755.     HRESULT hr;
  756.     int ttt=GetTickCount();
  757.     do{
  758.         hr=lpDirectPlay3A->Send(MyDPID,DPID_ALLPLAYERS,
  759.         DPSEND_GUARANTEED,lpData,Size);
  760.         count++;
  761.     }while(hr!=DP_OK/*&&(GetTickCount()-ttt)<60000*/);
  762.     if(hr!=DP_OK)return false;
  763.     return true;
  764. };
  765. bool SendToServer(DWORD Size,LPVOID lpData){
  766.     if(!int(lpDirectPlay3A)||NPlayers<2)return false;
  767.     int count=0;
  768.     HRESULT hr;
  769.     do{
  770.         hr=lpDirectPlay3A->Send(MyDPID,ServerDPID,0,
  771.         /*DPSEND_GUARANTEED,*/lpData,Size);
  772.         count++;
  773.     }while(hr!=DP_OK&&count<300);
  774.     if(hr!=DP_OK)return false;
  775.     return true;
  776. };
  777. void FreePDatas(){
  778.     for(int i=0;i<NPlayers;i++){
  779.         if(int(PData[i]))free(PData[i]);
  780.         PData[i]=NULL;
  781.     };
  782. };
  783. extern int RealLx;
  784. extern int RealLy;
  785. extern int LastKey;
  786. extern bool KeyPressed;
  787. void CBar(int x,int y,int Lx,int Ly,byte c);
  788. void ComeInGame(){
  789.     //NationalExcange;
  790.     static int nttm[3];
  791.     nttm[0]=0x12345678;
  792.     nttm[1]=MyDPID;
  793.     nttm[2]=MyRace;
  794.     SendToAllPlayers(12,nttm);
  795.     bool allOk=false;
  796.     int myid=-1;
  797.     for(int i=0;i<NPlayers;i++)if(MyDPID==PlayersID[i])myid=i;
  798.     for(i=0;i<8;i++){
  799.         PLNAT[i]=-1;
  800.     };
  801.     PLNAT[myid]=MyRace;
  802.     do{
  803.         ReceiveMessage(lpDPInfo);
  804.         DWORD* lp=(DWORD*)MyData;
  805.         if(lp){
  806.             if(lp[0]==0x12345678){
  807.                 for(i=0;i<NPlayers;i++){
  808.                     if(lp[1]==PlayersID[i]){
  809.                         PLNAT[i]=lp[2];
  810.                     };
  811.                 };
  812.                 allOk=true;
  813.                 for(i=0;i<NPlayers;i++){
  814.                     if(PLNAT[i]==-1)allOk=false;
  815.                 };
  816.             };
  817.         };
  818.         /*
  819.         ProcessMessages();
  820.         int x=(RealLx>>1)-100;
  821.         int y=RealLy>>1;
  822.         char ddd[128];
  823.         CBar(x-20,y-20,200,200,0);
  824.         ShowString(x,y,"Waiting for opponents...",&f16x16w);
  825.         y+=20;
  826.         for(i=0;i<8;i++){
  827.             sprintf(ddd,"PL%d :ID=%d , NAT=%d",i,PlayersID[i],PLNAT[i]);
  828.             ShowString(x,y,ddd,&f16x16w);
  829.             y+=16;
  830.         };
  831.         FlipPages();*/
  832.         if(KeyPressed&&LastKey==VK_F3){
  833.             IAmLeft();
  834.             return;
  835.         };
  836.     }while(!allOk);
  837.     PrepareGameMedia(myid);
  838.     //-----------
  839.     EBPos=0;
  840.     EBPos1=0;
  841.     ExBuf1[0]=ExDataID;
  842.     SetupEBufs();
  843.     RealTime=0;
  844.     ExBuf1[1]=0;
  845.     ExBuf[2]=0;
  846.     rpos=0;
  847.     SendToAllPlayers(12,ExBuf1);
  848.     PlayerMenuMode=0;
  849. };
  850. bool StartGame(){
  851.     DWORD BUF[35];
  852.     if(NPlayers<2)return false;
  853.     ServerDPID=MyDPID;
  854.     BUF[0]=0x037242F3;//start game code
  855.     BUF[1]=MyDPID;
  856.     BUF[2]=NPlayers;
  857.     memcpy(&BUF[3],PlayersID,32*4);
  858.     FreePDatas();
  859.     if(SendToAllPlayers(35*4,BUF)){
  860.         int ttm=GetTickCount();
  861.         bool xx;
  862.         do{
  863.             xx=false;
  864.             for(int j=0;j<NPlayers;j++){
  865.                 if(!int(PData[j]))xx=true;
  866.                 if(int(PData[j])&&(*(DWORD*)PData)!=0x773F2945) xx=true;
  867.             };
  868.         }while(xx&&GetTickCount()-ttm<200);
  869.         if(!xx){
  870.             ServerDPID=0;
  871.             return false;
  872.         };
  873.         GameInProgress=true;
  874.         StartMultiplayer.Close();
  875.         PlayerMenuMode=0;
  876.         ComeInGame();
  877.         tmtmt=0;
  878.         return true;
  879.     }else return false;
  880. };
  881. bool StartIGame(){
  882.     PrepareToGame();
  883.     DWORD BUF[48];
  884.     if(NPlayers<2)return false;
  885.     //BUF[0]=.....
  886.     //BUF[1]=Nation
  887.     //BUF[2],[3],[4],[5],[6],[7]-map name
  888.     ServerDPID=MyDPID;
  889.     BUF[0]=0x037242F3;//start game code
  890.     BUF[1]=MyRace;
  891.     for(int i=2;i<8;i++)BUF[i]=0;
  892.     strcpy((char*)&BUF[2],CurrentMap);
  893.     BUF[8]=MyDPID;
  894.     BUF[9]=NPlayers;
  895.     memcpy(&BUF[10],PlayersID,32*4);
  896.     FreePDatas();
  897.     if(SendToAllPlayers(42*4,BUF)){
  898.         //int ttm=GetTickCount();
  899.         //bool xx;
  900.         //do{
  901.         //    xx=false;
  902.         //    for(int j=0;j<NPlayers;j++){
  903.         //        if(!int(PData[j]))xx=true;
  904.         //        if(int(PData[j])&&(*(DWORD*)PData)!=0x773F2945) xx=true;
  905.         //    };
  906.         //}while(xx&&GetTickCount()-ttm<200);
  907.         //if(!xx){
  908.         //    ServerDPID=0;
  909.         //    return false;
  910.         //};
  911.         int ttm=GetTickCount();
  912.         bool xx;
  913.         do{
  914.         }while(xx&&GetTickCount()-ttm<400);
  915.         GameInProgress=true;
  916.         StartMultiplayer.Close();
  917.         PlayerMenuMode=0;
  918.         ComeInGame();
  919.         tmtmt=0;
  920.         return true;
  921.     }else return false;
  922. };
  923.  
  924. void AnalyseMessages(){
  925.     ReceiveMessage(lpDPInfo);
  926.     if(MyDPID!=ServerDPID){
  927.         DWORD* lp=(DWORD*)MyData;
  928.         if(lp){
  929.             if(lp[0]==0x037242F3&&!GameInProgress){
  930.                 //start game
  931.                 ServerDPID=lp[8];
  932.                 NPlayers=lp[9];
  933.                 memcpy(PlayersID,&lp[10],32*4);
  934.                 strcpy(CurrentMap,(char*)&lp[2]);
  935.                 PLNAT[0]=lp[1];
  936.                 //DWORD Ready=0x773F2945;
  937.                 //SendToServer(4,&Ready);
  938.                 GameInProgress=true;
  939.                 StartMultiplayer.Close();
  940.                 PlayerMenuMode=0;
  941.                 ComeInGame();
  942.             };
  943.         };
  944.     };
  945. };
  946. void xAnalyseMessages(){
  947.     ReceiveMessage(lpDPInfo);
  948.     if(MyDPID!=ServerDPID){
  949.         DWORD* lp=(DWORD*)MyData;
  950.         if(lp){
  951.             if(lp[0]==0x037242F3&&!GameInProgress){
  952.                 //start game
  953.                 ServerDPID=lp[1];
  954.                 NPlayers=lp[2];
  955.                 memcpy(PlayersID,&lp[3],32*4);
  956.                 //DWORD Ready=0x773F2945;
  957.                 //SendToServer(4,&Ready);
  958.                 GameInProgress=true;
  959.                 StartMultiplayer.Close();
  960.                 PlayerMenuMode=0;
  961.                 ComeInGame();
  962.             };
  963.         };
  964.     };
  965. };
  966. void IAmLeft(){
  967.     DWORD Left=PlExitID;
  968.     SendToAllPlayers(4,(void*)&PlExitID);
  969. };
  970.  
  971. int GetRLen(char* s,RLCFont* font);
  972. extern int LastKey;
  973. extern bool KeyPressed;
  974. void HandleMultiplayer(){
  975.     if(NPlayers<2)return;
  976.     DWORD ii=GetPIndex(MyDPID);
  977.     if(ii<0||ii>=NPlayers)return;
  978.     EBufs[ii].RealTime=RealTime;
  979.     EBufs[ii].RandIndex=PrevRpos;
  980.     memcpy(&EBufs[ii].Data,&ExBuf1[3],EBPos1);
  981.     EBufs[ii].Size=EBPos1;
  982.     int fff=GetTickCount();
  983.     int yyy;
  984.     //COUNTER=GetTickCount();
  985.     do{
  986.         ReceiveMessage(lpDPInfo);
  987.         yyy=(GetTickCount()-fff)>>6;
  988.         ProcessMessages();
  989.         if(yyy>50){
  990.             char* sss="╧└╙╟└. (F3-╬≥±εσΣΦφσφΦσ)";
  991.             int len=GetRLen(sss,&FPassive);
  992.             yyy=100;
  993.             ShowString(smapx+(smaplx<<(Shifter-1))-(len>>1),smapy+(smaply<<(Shifter-1)),sss,&FPassive);
  994.             FlipPages();
  995.             if(KeyPressed){
  996.                 if(LastKey==VK_F3){
  997.                     yyy=10000;
  998.                 };
  999.             };
  1000.         };
  1001.     }while(PresentEmptyBuf()&&yyy<1000);
  1002.     //COUNTER=GetTickCount()-COUNTER;
  1003.     if(yyy>=1000){
  1004.         sprintf(Prompt,"╤Γ τⁿ ≡ατε≡Γαφα.");
  1005.         PromptTime=300;
  1006.         NPlayers=1;
  1007.         IAmLeft();
  1008.         return;
  1009.     };
  1010.     EBPos1=EBPos;
  1011.     memcpy(&ExBuf1[3],ExBuf,EBPos1);
  1012.     ExBuf1[2]=rpos;
  1013.     PrevRpos=rpos;
  1014.     ExBuf1[1]=RealTime+1;
  1015.     ExBuf1[0]=ExDataID;
  1016.     SendToAllPlayers(EBPos1+12,ExBuf1);
  1017.     EBPos=0;
  1018.     UpdateEBufs();
  1019.     RealTime++;
  1020. };
  1021. void CloseMPL(){
  1022.     if(int(lpDirectPlay3A))
  1023.         lpDirectPlay3A->Close();
  1024.     lpDirectPlay3A=NULL;
  1025. };
  1026. void PlayerMenuWork(){
  1027.     if(PlayerMenuMode==1){
  1028.         if((!SingleMulti.Active)&&
  1029.            (!ChooseConn.Active)&&
  1030.            (!ChooseSession.Active)&&
  1031.            (!StartMultiplayer.Active))
  1032.                 SingleMulti.ShowModal();
  1033.         if(SingleMulti.Active){
  1034.             switch(SingleMulti.choose){
  1035.             case 0:
  1036.                 PlayerMenuMode=2;
  1037.                 SingleMulti.Close();
  1038.                 Lpressed=false;
  1039.                 return;
  1040.             case 1:
  1041.                 SingleMulti.Close();
  1042.                 ChooseConn.ShowModal();
  1043.                 Lpressed=false;
  1044.                 return;
  1045.             case 2:
  1046.                 SingleMulti.Close();
  1047.                 CloseExplosions();
  1048.                 void ShutdownMultiplayer();
  1049.                 PostMessage(hwnd, WM_CLOSE, 0, 0);
  1050.                 return;
  1051.             };
  1052.         };
  1053.         if(ChooseConn.Active){
  1054.             if(ChooseConn.choose==ChooseConn.NItems-1){
  1055.                 ChooseConn.Close();
  1056.                 Lpressed=false;
  1057.                 SingleMulti.ShowModal();
  1058.                 return;
  1059.             };
  1060.             if(ChooseConn.choose>=0){
  1061.                 CreateMultiplaterInterface();
  1062.                 if FAILED(lpDirectPlay3A->InitializeConnection(
  1063.                     lplpConnectionBuffer[ChooseConn.choose],0)) return;
  1064.                 EnumerateSessions();
  1065.                 ChooseConn.Close();
  1066.                 Lpressed=false;
  1067.                 ChooseSession.ShowModal();
  1068.                 return;
  1069.             };
  1070.         };
  1071.         if(ChooseSession.Active){
  1072.             //EnumerateSessions();
  1073.             //ChooseSession.Active=true;
  1074.             if(ChooseSession.choose==NSessions+3){
  1075.                 ChooseSession.Close();
  1076.                 Lpressed=false;
  1077.                 ChooseConn.ShowModal();
  1078.                 return;
  1079.             };
  1080.             if(ChooseSession.choose>=0&&
  1081.                 ChooseSession.choose<NSessions){
  1082.                 if(JoinToSession(ChooseSession.choose)){
  1083.                     ChooseSession.Close();
  1084.                     Lpressed=false;
  1085.                     StartMultiplayer.ShowModal();
  1086.                     return;
  1087.                 };
  1088.  
  1089.             };
  1090.             if(ChooseSession.choose==NSessions+2){
  1091.                 if(CreateSession()){
  1092.                     ChooseSession.Close();
  1093.                     Lpressed=false;
  1094.                     StartMultiplayer.ShowModal();
  1095.                     return;
  1096.                 };
  1097.             };
  1098.         };
  1099.         if(StartMultiplayer.Active){
  1100.             AnalyseMessages();
  1101.             EnumeratePlayers();
  1102.             StartMultiplayer.Active=true;
  1103.             if(StartMultiplayer.choose==1){
  1104.                 StartMultiplayer.Close();
  1105.                 if(int(lpDirectPlay3A))
  1106.                     lpDirectPlay3A->Close();
  1107.                 Lpressed=false;
  1108.                 ChooseConn.ShowModal();
  1109.                 return;
  1110.             };
  1111.             if(StartMultiplayer.choose==0){
  1112.                 StartGame();
  1113.                 return;
  1114.             };
  1115.         };
  1116.     };
  1117. };