NETWORK.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:20k
源码类别:

Windows编程

开发平台:

Visual C++

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