home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / rpc / mazelord / network.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-07  |  19.5 KB  |  554 lines

  1. /***********************************************************************
  2. File:   Network.c
  3.  
  4. Abstract:
  5.  
  6.     This is the network communications module for MazeLords. It contains functions
  7.     to implement mailslots, as well as the various protocols and so-on required
  8.     for communications.
  9.  
  10.  
  11. Contents:
  12.  
  13.     MemCRC() -- Generates a 'unique' LONG for different data structures
  14.     SendNetMessage() -- Transmit a pre-made structure to other players
  15.     MailWatchThread() -- Thread process to watch for new mail
  16.     InitNetwork() -- Create mailslot, Send out ID message to network.
  17.     ProcessNewMail() -- Process newly recieved data packets
  18.  
  19.  
  20. ************************************************************************/
  21.  
  22. #include <windows.h>
  23. #include <mmsystem.h>
  24. #include "winmaze.h"
  25. #include "mazproto.h"
  26. #include "net.h"
  27. #include "crctable.h"
  28.  
  29.  
  30.  
  31. /*=====================================================================
  32. Function:   MemCRC()
  33.  
  34. Inputs:     Buffer & buffer length to CRC
  35.  
  36. Outputs:    Returns single Long corresponding to CRC for structure
  37.  
  38. Abstract:
  39.     The CRC should provide a unique ID for each player, provided ANY
  40.     information in their data structures is unique. Each player is
  41.     responsible for generating their ID & transmitting it to the other
  42.     players.
  43. ======================================================================*/
  44.  
  45. unsigned long MemCRC(
  46.     LPSTR buffer,
  47.     int bytes
  48.     )
  49. {
  50.     unsigned long crc = 0xFFFFFFFF;
  51.     LPSTR p;
  52.  
  53.     for ( p = buffer; bytes > 0; bytes-- ) {
  54.         crc = ( crc >> 8 ) ^ CRCtable[(unsigned char) ((unsigned char) crc ^ *p++ ) ];
  55.         }
  56.  
  57.     return ( crc ^ 0xFFFFFFFF );
  58. }
  59.  
  60.  
  61. /*=====================================================================
  62. Function:   SendNetMessage()
  63.  
  64. Inputs:     Source, destination, structure to send, packet type
  65.  
  66. Outputs:    Returns success/failure
  67.  
  68. Abstract:
  69.     SendNetMessage will send a message to all mazelords mailslots in the
  70.     current domain.  Note that this message is broadcast once. It is up
  71.     to the individual recipients to decide whether it is addressed to them,
  72.     or a general message (sent to -1).
  73. ======================================================================*/
  74.  
  75. BOOL SendNetMessage(
  76.     unsigned long ulSender,
  77.     unsigned long ulDest,
  78.     LPVOID lpStruct,
  79.     DWORD dwPacketType
  80.     )
  81. {
  82.     BOOL bResult=TRUE;
  83.     HANDLE hFile;
  84.     DWORD dwScratch,dwLength;
  85.     char cBuff[MAX_PACKET_SIZE];
  86.     LPSTR lpStr;
  87.     NetPacketType FAR *lpN;
  88.     PlayerInfoType FAR *lppiInfo,FAR *lppiInfo2;
  89.     PositionType FAR *lpptPos,FAR *lpptPos2;
  90.     int FAR *iScore;
  91.     IntoneType FAR *itIntone;
  92.  
  93.     if (!bNetworked) {
  94.         return(TRUE);
  95.         }
  96.  
  97.     lpN = (NetPacketType FAR *) cBuff;
  98.     lpN->ulSender = (ulSender)? ulSender : ptSelf.ulID;
  99.     lpN->ulDest = ulDest;
  100.     lpN->dwPacketType = dwPacketType;
  101.     dwLength = sizeof(NetPacketType);
  102.  
  103.     //
  104.     // determine size, type of packet and fill out info accordingly.
  105.     //
  106.     lpStr = (LPSTR) &lpN->cData;
  107.  
  108.     switch(dwPacketType) {
  109.  
  110.         case NP_NEWPLAYER:
  111.             lppiInfo = (PlayerInfoType FAR *) lpStr;
  112.             lppiInfo2 = (PlayerInfoType FAR *) lpStruct;
  113.             *lppiInfo = *lppiInfo2;
  114.             dwLength += sizeof(PlayerInfoType);
  115.             break;
  116.  
  117.         case NP_REQUESTIDENTITY:
  118.         case NP_LEAVINGGAME:
  119.         case NP_HITCONFIRM:
  120.             break;
  121.  
  122.         case NP_MOVETO:
  123.         case NP_SHOTFIRED:
  124.             lpptPos = (PositionType FAR *) lpStr;
  125.             lpptPos2 = (PositionType FAR *) lpStruct;
  126.             *lpptPos = *lpptPos2;
  127.             dwLength += sizeof(PositionType);
  128.             break;
  129.  
  130.         case NP_SCORE:
  131.             iScore = (int FAR *) lpStr;
  132.             *iScore = ptSelf.iScore;
  133.             dwLength += sizeof(int);
  134.             break;
  135.  
  136.         case NP_INTONE:
  137.             itIntone = (IntoneType FAR *) lpStr;
  138.             *itIntone = *((IntoneType FAR *) lpStruct);
  139.             dwLength += sizeof(IntoneType);
  140.             dwLength -= (131 - itIntone->dwLen);
  141.             break;
  142.  
  143.         default:
  144.             MessageBox((HWND)NULL,GetStringRes(IDS_BADPCKTXMITFAIL),"SendNetMessage",
  145.                        MB_ICONEXCLAMATION|MB_APPLMODAL);
  146.             break;
  147.         }
  148.  
  149. #ifdef WIN32
  150.     hFile = CreateFile("\\\\*\\mailslot\\mazemslt",
  151.                      GENERIC_WRITE,
  152.                      FILE_SHARE_READ,
  153.                      NULL,
  154.                      OPEN_EXISTING,
  155.                      FILE_ATTRIBUTE_NORMAL,
  156.                      NULL);
  157.  
  158.     bResult = (hFile != INVALID_HANDLE_VALUE);
  159.  
  160.     bResult = bResult &&
  161.               WriteFile(hFile,cBuff,dwLength+1,&dwScratch,NULL);
  162.  
  163.     return(bResult && CloseHandle(hFile));
  164. #else // else it's any operating system except WIN32
  165.     return(TRUE);
  166. #endif
  167. }
  168.  
  169.  
  170.  
  171. /*=====================================================================
  172. Function:   MailWatchThread()
  173.  
  174. Inputs:     Handle to mailslot to watch
  175.  
  176. Outputs:    none
  177.  
  178. Abstract:
  179.     This is a thread which is spawned. As soon as it sees a mail message
  180.     is queued up, it sends a message to the main window notifying Maze
  181.     Lords that new mail has been received.  This is done 5 times a second.
  182. ======================================================================*/
  183.  
  184. void MailWatchThread(
  185.     HANDLE hMailSlot
  186.     )
  187. {
  188.     DWORD cbMaxMsg,cbNextMsg,cMsg,dwReadTimeout;
  189. #ifdef WIN32
  190.     while(TRUE) {
  191.  
  192.         Sleep(200);
  193.         if (GetMailslotInfo(hMailSlot,&cbMaxMsg,&cbNextMsg,&cMsg,&dwReadTimeout)) {
  194.             if (cMsg > 0) {
  195.                 PostMessage(hWndMain,WM_COMMAND,IDT_NEWMAIL,0);
  196.                 }
  197.             }
  198.         }
  199. #endif
  200.  
  201.     //
  202.     // We shouldn't ever get here.
  203.     //
  204.     return;
  205. }
  206.  
  207.  
  208.  
  209. /*=====================================================================
  210. Function:   InitNetwork()
  211.  
  212. Inputs:     none
  213.  
  214. Outputs:    returns success/failure
  215.  
  216. Abstract:
  217.     InitNetwork takes care of creating a mailslot for this user, and
  218.     sending out a packet saying that we're joining the game.
  219.     FALSE indicates that there was a fatal error starting the network.
  220. ======================================================================*/
  221.  
  222. BOOL InitNetwork(
  223.     void
  224.     )
  225. {
  226.     DWORD dwScratch;
  227.     BOOL bRet;
  228.     PlayerInfoType ptPlayScr;
  229.  
  230.     bRet = TRUE;
  231.  
  232.     //
  233.     // initialize player list
  234.     //
  235.     ptPlayers.next = (PlayerType FAR *)NULL;
  236.  
  237.     if (!bNetworked) {
  238.         hMailSlot = NULL;
  239.         return(TRUE);
  240.         }
  241.  
  242. #ifdef WIN32
  243.     hMailSlot = CreateMailslot("\\\\.\\mailslot\\mazemslt",0,0,NULL);
  244.     if (hMailSlot == INVALID_HANDLE_VALUE) {
  245.         MessageBox(NULL,GetStringRes(IDS_CREMSLOTFAIL),
  246.     GetStringRes2(IDS_NETINIT), MB_ICONEXCLAMATION|MB_APPLMODAL);
  247.         bRet = FALSE;
  248.         }
  249.  
  250.     if (! CreateThread((LPSECURITY_ATTRIBUTES) NULL,
  251.                        0,
  252.                        (LPTHREAD_START_ROUTINE)MailWatchThread,
  253.                        (LPVOID)hMailSlot,
  254.                        0,&dwScratch)) {
  255.         MessageBox(NULL,GetStringRes(IDS_CREMWATCHTHRFAIL),
  256.     GetStringRes2(IDS_NETINIT), MB_ICONEXCLAMATION|MB_APPLMODAL);
  257.         bRet = FALSE;
  258.         }
  259. #endif
  260.     ptPlayScr.ulID = ptSelf.ulID;
  261.     ptPlayScr.dwPID = ptSelf.dwPID;
  262.     lstrcpy(ptPlayScr.cUserName,ptSelf.cUserName);
  263.     lstrcpy(ptPlayScr.cComputerName,ptSelf.cComputerName);
  264.     ptPlayScr.ix = ptSelf.Pos.ix;
  265.     ptPlayScr.iy = ptSelf.Pos.iy;
  266.     ptPlayScr.bFacing = ptSelf.Pos.Facing;
  267.     ptPlayScr.iScore = ptSelf.iScore;
  268.     ptPlayScr.iPicNum = ptSelf.iPicNum;
  269.     ptPlayScr.iGridNum = ptSelf.iGridNum;
  270.     ptPlayScr.pGridLoc = ptSelf.pGridLoc;
  271.  
  272.     return(bRet&&SendNetMessage(0,0,(LPVOID) &ptPlayScr,NP_NEWPLAYER));
  273. }
  274.  
  275.  
  276. /*=====================================================================
  277. Function:   ProcessNewMail()
  278.  
  279. Inputs:     none
  280.  
  281. Outputs:    none
  282.  
  283. Abstract:
  284.     ProcessNewMail is responsible for updating character positions, asking
  285.     for more information, etc.
  286. ======================================================================*/
  287.  
  288. void ProcessNewMail(
  289.     void
  290.     )
  291. {
  292.     DWORD cbMaxMsg,cbNextMsg,cMsg,dwReadTimeout;
  293.     NetPacketType FAR *NPkt;
  294.     PlayerInfoType FAR *piPlayerPacket,piScratch;
  295.     PlayerType FAR *ptTrav;
  296.     PositionType FAR *ptPosPacket;
  297.     BOOL bFound,bDrawMessageSent;
  298.     int ix,iy;
  299.     BYTE bSquare1, bSquare2,Facing;
  300.     char cBuff[257],cNetMessBuff[400];
  301.     int FAR *iScore;
  302.     IntoneType FAR *itIntone;
  303.  
  304. #ifdef WIN32
  305.     GetMailslotInfo(hMailSlot,&cbMaxMsg,&cbNextMsg,&cMsg,&dwReadTimeout);
  306.     bDrawMessageSent = FALSE;
  307.  
  308.     while (cMsg) {
  309.         if (!ReadFile(hMailSlot,cNetMessBuff,cbNextMsg,&cbMaxMsg,(LPOVERLAPPED) NULL)) {
  310.             MessageBox(NULL,GetStringRes(IDS_RDMSLOTFAIL),"ProcessNewMail",
  311.                        MB_ICONEXCLAMATION|MB_APPLMODAL);
  312.             }
  313.  
  314.         NPkt = (NetPacketType FAR *) cNetMessBuff;
  315.  
  316.         //
  317.         // Don't process the message if it's one of our own
  318.         //
  319.         if ((NPkt->ulSender != ptSelf.ulID)&&
  320.             ((NPkt->ulDest == ptSelf.ulID)||(NPkt->ulDest == 0))
  321.            ) {
  322.  
  323.             piPlayerPacket = (PlayerInfoType FAR *) &(NPkt->cData);
  324.             ptPosPacket = (PositionType FAR *) &(NPkt->cData);
  325.             iScore = (int FAR *) &(NPkt->cData);
  326.             itIntone = (IntoneType FAR *) &(NPkt->cData);
  327.  
  328.             bFound = FALSE;
  329.             ptTrav = &ptPlayers;
  330.  
  331.             while (ptTrav->next != NULL) {
  332.                 if (ptTrav->next->ulID == NPkt->ulSender) {
  333.                     bFound = TRUE;
  334.                     break;
  335.                     }
  336.                 ptTrav = ptTrav->next;
  337.                 }
  338.  
  339.             if ((!bFound)&&(NPkt->dwPacketType != NP_NEWPLAYER)) {
  340.                 if(!SendNetMessage(0,NPkt->ulSender,NULL,NP_REQUESTIDENTITY)) {
  341.                     MessageBox(NULL,GetStringRes(IDS_SNDPCKTFAIL),"ProcessNewMail",
  342.                                MB_ICONEXCLAMATION|MB_APPLMODAL);
  343.                     }
  344.                 }
  345.  
  346.             switch (NPkt->dwPacketType) {
  347.  
  348.                 case (NP_NEWPLAYER):
  349.                     if (!bFound) {
  350.                         ptTrav->next = NewPlayer(piPlayerPacket->ulID,
  351.                                      piPlayerPacket->dwPID,
  352.                                      piPlayerPacket->cUserName,
  353.                                      piPlayerPacket->cComputerName,
  354.                                      piPlayerPacket->ix,
  355.                                      piPlayerPacket->iy,
  356.                                      piPlayerPacket->bFacing,
  357.                                      piPlayerPacket->iScore,
  358.                                      piPlayerPacket->iPicNum,
  359.                                      piPlayerPacket->iGridNum,
  360.                                      piPlayerPacket->pGridLoc.x,
  361.                                      piPlayerPacket->pGridLoc.y,
  362.                                      ptTrav->next);
  363.                         if (!AddPic(piPlayerPacket->iPicNum)) {
  364.                             ptTrav->next->iPicNum = PIC_DEFAULT;
  365.                             sprintf(cBuff, GetStringRes(IDS_FMT_BADPICNUM),
  366.                                     piPlayerPacket->iPicNum,piPlayerPacket->cComputerName);
  367.                             PrintTextLine(cBuff);
  368.                             AddPic(PIC_DEFAULT);
  369.                             }
  370.  
  371.                         //
  372.                         // After we add the user to our own database,
  373.                         // let him know we exist.
  374.                         //
  375.                         sprintf(cBuff,GetStringRes(IDS_FMT_JOIN),ptTrav->next->cUserName);
  376.                         PrintTextLine(cBuff);
  377.  
  378.                         piScratch.ulID = ptSelf.ulID;
  379.                         piScratch.dwPID = ptSelf.dwPID;
  380.                         strcpy(piScratch.cUserName,ptSelf.cUserName);
  381.                         strcpy(piScratch.cComputerName,ptSelf.cComputerName);
  382.                         piScratch.ix = ptSelf.Pos.ix;
  383.                         piScratch.iy = ptSelf.Pos.iy;
  384.                         piScratch.bFacing = ptSelf.Pos.Facing;
  385.                         piScratch.iScore = ptSelf.iScore;
  386.                         piScratch.iPicNum = ptSelf.iPicNum;
  387.                         piScratch.iGridNum = ptSelf.iGridNum;
  388.                         piScratch.pGridLoc = ptSelf.pGridLoc;
  389.                         if (!SendNetMessage(0,NPkt->ulSender,&piScratch,NP_NEWPLAYER)) {
  390.                             MessageBox(NULL,GetStringRes(IDS_SNDPCKTFAIL),"ProcessNewMail",
  391.                                              MB_ICONEXCLAMATION|MB_APPLMODAL);
  392.                             }
  393.  
  394.                         //
  395.                         // Finally, do a redraw to make sure if he's in
  396.                         // line of sight we see him. */
  397.                         //
  398.                         PostMessage(hWndMaze,WM_COMMAND,IDM_DRAWPLAYERS,0);
  399.                         PostMessage(hWndScore,WM_COMMAND,WC_ADDSCORE,ptTrav->next->ulID);
  400.                         }
  401.                     break;
  402.  
  403.                 case (NP_REQUESTIDENTITY):
  404.                     piScratch.ulID = ptSelf.ulID;
  405.                     piScratch.dwPID = ptSelf.dwPID;
  406.                     strcpy(piScratch.cUserName,ptSelf.cUserName);
  407.                     strcpy(piScratch.cComputerName,ptSelf.cComputerName);
  408.                     piScratch.ix = ptSelf.Pos.ix;
  409.                     piScratch.iy = ptSelf.Pos.iy;
  410.                     piScratch.bFacing = ptSelf.Pos.Facing;
  411.                     piScratch.iScore = ptSelf.iScore;
  412.                     piScratch.iPicNum = ptSelf.iPicNum;
  413.                     piScratch.iGridNum = ptSelf.iGridNum;
  414.                     piScratch.pGridLoc = ptSelf.pGridLoc;
  415.                     if (!SendNetMessage(0,NPkt->ulSender,&piScratch,NP_NEWPLAYER)) {
  416.                         MessageBox(NULL,GetStringRes(IDS_SNDPCKTFAIL),"ProcessNewMail",
  417.                                              MB_ICONEXCLAMATION|MB_APPLMODAL);
  418.                         }
  419.  
  420.                     break;
  421.  
  422.                 case (NP_MOVETO):
  423.                     if (bFound) {
  424.                         ptTrav->next->Pos = *ptPosPacket;
  425.                         if (ptTrav->next->Drawn) {
  426.                             if (!bBitmapDraw) {
  427.                                 InvalidateRect(hWndMaze,&ptTrav->next->rDrawn,TRUE);
  428.                                 }
  429. //
  430. //BUGBUG -- drawing problem for bitmaps
  431. //
  432.                             ptTrav->next->Drawn=FALSE;
  433.                             }
  434.                         else {
  435.                             if (!bDrawMessageSent) {
  436.                                 PostMessage(hWndMaze,WM_COMMAND,IDM_DRAWPLAYERS,0);
  437.                                 bDrawMessageSent = TRUE;
  438.                                 }
  439.                             }
  440.                         PostMessage(hWndScore,WM_COMMAND,WC_UPDATEDIRECTION,ptTrav->next->ulID);
  441.                         }
  442.                     break;
  443.  
  444.                 case (NP_SHOTFIRED):
  445.                     if (bFound) {
  446.  
  447.                         PlaySound("othrlasr.wav",NULL,SND_FILENAME|SND_ASYNC);
  448.  
  449.                         //
  450.                         // if the shot was fired in the same 'x' or 'y'
  451.                         // plane, we may have been hit!
  452.                         //
  453.                         if ((ptPosPacket->ix == ptSelf.Pos.ix)||
  454.                             (ptPosPacket->iy == ptSelf.Pos.iy)
  455.                            ) {
  456.  
  457.                             ix = ptPosPacket->ix;
  458.                             iy = ptPosPacket->iy;
  459.                             Facing = ptPosPacket->Facing;
  460.  
  461.                             bSquare2 = bMaze[ix][iy];
  462.  
  463.                             do {
  464.                                 //
  465.                                 // if we're hit, handle it!
  466.                                 //
  467.                                 if ((!InSanctuary(&ptSelf.Pos))&&(ptSelf.Pos.ix == ix)&&(ptSelf.Pos.iy == iy)) {
  468.                                     if (!SendNetMessage(0,NPkt->ulSender,NULL,NP_HITCONFIRM)) {
  469.                                         MessageBox(NULL,GetStringRes(IDS_SNDPCKTFAIL),"MazeWndProc",
  470.                                              MB_ICONEXCLAMATION|MB_APPLMODAL);
  471.                                         }
  472.                                     sprintf(cBuff,GetStringRes(IDS_FMT_ZAPPEDYOU),ptTrav->next->cUserName);
  473.                                     PrintTextLine(cBuff);
  474.                                     KillSelf();
  475.                                     break;
  476.                                     }
  477.                                 //
  478.                                 // otherwise, keep checking.
  479.                                 //
  480.                                 bSquare1 = bSquare2;
  481.                                 bSquare2 = bMaze[ix = ADJ_X(ix,Facing)][iy = ADJ_Y(iy,Facing)];
  482.                                 } while (!((bSquare1 & Facing)||(bSquare2 & BACK_TO_ABS(Facing))));
  483.                             }
  484.                         }
  485.  
  486.                     break;
  487.  
  488.                 case (NP_LEAVINGGAME):
  489. //
  490. // ***BUGBUG*** Might cause problems if character leaving is on screen
  491. //
  492.                     if (bFound) {
  493.                         sprintf(cBuff,GetStringRes(IDS_FMT_LEFT),ptTrav->next->cUserName);
  494.                         PrintTextLine(cBuff);
  495.                         PostMessage(hWndScore,WM_COMMAND,WC_DELETESCORE,ptTrav->next->ulID);
  496.                         ptTrav->next = DeletePlayer(ptTrav->next);
  497.                         PostMessage(hWndMaze,WM_COMMAND,IDM_DRAWPLAYERS,0);
  498.                         }
  499.                     break;
  500.  
  501.                 case (NP_HITCONFIRM):
  502.                     PlaySound("squish.wav",NULL,SND_FILENAME|SND_ASYNC);
  503.                     if (bFound) {
  504.                         FadePic(ptTrav->next->iPicNum,
  505.                                 ptTrav->next->Pos.Facing,
  506.                                 hMazeDC,
  507.                                 &ptTrav->next->rFrom,
  508.                                 &ptTrav->next->rDrawn);
  509.                         sprintf(cBuff,GetStringRes(IDS_FMT_HIT),ptTrav->next->cUserName);
  510.                         PrintTextLine(cBuff);
  511.                         }
  512.                     ptSelf.iScore += 50;
  513.                     iPlayersKilled++;
  514.  
  515.                     SendNetMessage(0,0,NULL,NP_SCORE);
  516.                     PostMessage(hWndScore,WM_COMMAND,WC_UPDATESCORE,ptSelf.ulID);
  517.                     break;
  518.  
  519.                 case (NP_SCORE):
  520.                     if (bFound) {
  521.                         ptTrav->next->iScore = *iScore;
  522.                         PostMessage(hWndScore,WM_COMMAND,WC_UPDATESCORE,ptTrav->next->ulID);
  523.                         }
  524.                     break;
  525.  
  526.                 case NP_INTONE:
  527.                     if (bFound) {
  528.                         ix = ptSelf.Pos.ix - itIntone->Pos.ix;
  529.                         iy = ptSelf.Pos.iy - itIntone->Pos.iy;
  530.                         if ((ix*ix + iy*iy) <= (itIntone->iLoudness * itIntone->iLoudness)) {
  531.                             sprintf(cBuff,"[%s] - \"%s\"",ptTrav->next->cUserName,
  532.                                     itIntone->cBuff);
  533.                             PrintTextLine(cBuff);
  534.                             }
  535.                         }
  536.                     break;
  537.  
  538.                 default:
  539.                     MessageBox(NULL,GetStringRes(IDS_BADMSG),"ProcessNewMail",
  540.                                 MB_ICONEXCLAMATION|MB_APPLMODAL);
  541.                     break;
  542.                 }
  543.             }
  544.  
  545.         GetMailslotInfo(hMailSlot,&cbMaxMsg,&cbNextMsg,&cMsg,&dwReadTimeout);
  546.         }
  547.  
  548. #endif // end if WIN32. This whole function is not present for WIN16.
  549.  
  550.     return;
  551.  
  552. }
  553.  
  554.