home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / Samples / SprocketExamples / SprocketInvaders / Source / NetSprocketSupport.c < prev    next >
Encoding:
Text File  |  1998-07-14  |  18.5 KB  |  843 lines  |  [TEXT/CWIE]

  1. //•    ------------------------------------------------------------------------------------------    •
  2. //•
  3. //•    Copyright © 1996 Apple Computer, Inc., All Rights Reserved
  4. //•
  5. //•
  6. //•        You may incorporate this sample code into your applications without
  7. //•        restriction, though the sample code has been provided "AS IS" and the
  8. //•        responsibility for its operation is 100% yours.  However, what you are
  9. //•        not permitted to do is to redistribute the source as "DSC Sample Code"
  10. //•        after having made changes. If you're going to re-distribute the source,
  11. //•        we require that you make it clear in the source that the code was
  12. //•        descended from Apple Sample Code, but that you've made changes.
  13. //•
  14. //•        Authors:
  15. //•            Jamie Osborne
  16. //•
  17. //•    ------------------------------------------------------------------------------------------    •
  18.  
  19. //•    ------------------------------    Includes
  20.  
  21. #include <Dialogs.h>
  22. #include <Fonts.h>
  23. #include <Lists.h>
  24. #include <QDOffScreen.h>
  25. #include <Resources.h>
  26. #include <Sound.h>
  27. #include <TextEdit.h>
  28. #include <TextUtils.h>
  29.  
  30. #include "CommonStuff.h"
  31. #include "EventHandler.h"
  32. #include "NetSprocketSupport.h"
  33.  
  34. //•    ------------------------------    Private Definitions
  35. //•    ------------------------------    Private Types
  36.  
  37. enum
  38. {
  39.     kWaitForPlayersDialogID = 1000
  40. };
  41.  
  42. enum
  43. {
  44.     kOKButton = 1, 
  45.     kCancelButton,
  46.     kPlayerListLabel,
  47.     kPlayerList,
  48.     kChatWindow,
  49.     kChatTextEntry,
  50.     kStatus
  51. };
  52.         
  53. typedef struct DialogInfo
  54. {
  55.     ListHandle    playerList;
  56.     TEHandle    teHandle;
  57.     Str32        nameListBuffer[kMaxPlayers];
  58. } DialogInfo;
  59.  
  60. //•    ------------------------------    Private Variables
  61. //•    ------------------------------    Private Functions
  62.  
  63. static void GetChooserName(Str255 name);
  64. static void SendChatText(StringPtr inText, NSpPlayerID inTo);
  65. static void DoHandleMessage(NSpMessageHeader *inMessage);
  66. static pascal void PlayerListProc(WindowPtr dialog, SInt16 itemNo);
  67. static pascal void ChatViewProc(WindowPtr dialog, SInt16 itemNo);
  68. static void SetDialogtemUserProc(DialogPtr dialog, SInt16 item, UserItemUPP theProc);
  69. static void WatchForPlayers(DialogPtr dialog);
  70. static OSStatus SendWelcomeMessage(NSpPlayerID inID);
  71. static void MakePlayerList(DialogPtr dialog);
  72. static void SendText(DialogPtr dialog);
  73.  
  74. static pascal Boolean DialogEventFilter(DialogPtr dialog, EventRecord *event, SInt16 *itemHit);
  75.  
  76. static void DoHandleChatTextMessage(ChatTextMessage *inMessage, DialogPtr dialog);
  77. static void PrintPlayerText(StringPtr inText, NSpPlayerID inPlayer, TEHandle inTEHandle);
  78.  
  79. static void DoHandlePlayerInput(PlayerInputMessage *inMessage);
  80. static void DoHandleEndGameMessage(void);
  81. static void DoHandleStartGame(StartGameMessage *inMessage);
  82. static void DisableDialogItem(DialogPtr theDialog, SInt16 theItem);
  83.  
  84. //•    ------------------------------    Public Variables
  85.  
  86. NSpGameReference    gNetGame = NULL;
  87. Boolean                gIAmHost = false;
  88. Str31                kNetworkGameName = "\pNetSprocket Game";
  89. Str31                kJoinDialogLabel = "\pChoose a Game:";
  90. Str31                 kNBPType = "\pInvd";        // This should be the same as kGameID
  91. NetworkState        gNetState;
  92. Str31                kSeparatorString = "\p: ";
  93. SInt8                kReturn = '\r';
  94. Boolean                gGotEndGameMessage = false;
  95. Boolean                gReceivedInput;
  96. Boolean                gNetSprocketPresent;
  97.  
  98. #pragma mark === Utility functions ===
  99.  
  100. //•    --------------------    NetSprocketPresent
  101. //•
  102. //•    returns TRUE if networking is present, FALSE otherwise
  103.  
  104. Boolean
  105. NetSprocketPresent(void)
  106. {
  107.     return (NSpInitialize != nil);
  108. }
  109.  
  110. //•    --------------------    GetChooserName
  111.  
  112. static void
  113. GetChooserName(Str255 name)
  114. {
  115. StringHandle    userName;
  116.     
  117.     userName = GetString(-16096);
  118.     FAIL_NIL(userName, "GetString for Chooser Name failed");
  119.     
  120.     CopyPStr(*userName, name);
  121.     ReleaseResource ((Handle) userName);
  122.  
  123. error:
  124.     return;
  125. }
  126.  
  127. #pragma mark === Networking stuff ===
  128.  
  129. //•    --------------------    InitNetworking
  130.  
  131. Boolean
  132. InitNetworking(void)
  133. {
  134. OSStatus    status;
  135.     
  136.     if (! NetSprocketPresent())
  137.         return (false);
  138.         
  139.     //•    Initialize NetSprocket
  140.     status = NSpInitialize(kStandardMessageSize, kBufferSize, kQElements, kGameID, kTimeout);
  141.     FAIL_OSSTATUS(status, "NSpInitialize failed");
  142.     if (status != noErr)
  143.         return (false);
  144.  
  145.     gNetState = kSlacking;
  146.     
  147.     return (true);
  148.     
  149. error:
  150.     return (false);
  151. }
  152.  
  153. //•    --------------------    ShutdownNetworking
  154.  
  155. void
  156. ShutdownNetworking(void)
  157. {
  158. OSStatus    status;
  159.     
  160.     if (gNetGame)
  161.         status = NSpGame_Dispose( gNetGame, kNSpGameFlag_ForceTerminateGame );
  162.  
  163.     gNetState = kSlacking;
  164.     gNetGame = NULL;
  165. }
  166.  
  167.  
  168. //•    --------------------    DoHostGame
  169. //•
  170. //•    Returns TRUE if the user says OK (and NetSprocket doesn't return an error), false otherwise
  171.  
  172. Boolean
  173. DoHostGame(void)
  174. {
  175. OSStatus                    status = noErr;
  176. NSpProtocolListReference    theList = NULL;
  177. Str31                        playerName, gameName, password;
  178. Boolean                     OKHit;
  179.     
  180.     status = NSpProtocolList_New(NULL, &theList);
  181.     FAIL_OSSTATUS(status, "Couldn't create a protocol list");
  182.         
  183.     //    Do the host dialog
  184.     GetChooserName(playerName);
  185.     CopyPStr(kNetworkGameName, gameName);
  186.     password[0] = 0;
  187.  
  188.     OKHit = NSpDoModalHostDialog(theList, gameName, playerName, password, NULL);
  189.     if (!OKHit)
  190.         return (false);
  191.         
  192.     //    Now host the game
  193.     status = NSpGame_Host(&gNetGame, theList, kMaxPlayers, gameName,
  194.                 password, playerName, 0, kNSpClientServer, 0);
  195.  
  196.     FAIL_OSSTATUS(status, "NSpGame_Host returned an error");
  197.     
  198.     NSpProtocolList_Dispose(theList);
  199.     gIAmHost = true;
  200.     gNetState = kHosting;
  201.     
  202.     // let all the players join
  203.     OKHit = WaitForAllPlayers();
  204.     if (OKHit == false)
  205.     {
  206.         ShutdownNetworking();
  207.         return (false);        
  208.     }
  209.     else
  210.     {
  211.         gNetState = kStarting;
  212.         SendStartGame();
  213.     }
  214.     
  215.     return (true);
  216.     
  217. error:
  218.  
  219.     if (theList)
  220.         NSpProtocolList_Dispose(theList);
  221.         
  222.     return (false);
  223. }
  224.  
  225. //•    --------------------    DoJoinGame
  226. //•
  227. //•    Returns TRUE if the user says OK (and NetSprocket doesn't return an error), false otherwise
  228.  
  229. Boolean
  230. DoJoinGame(void)
  231. {
  232. NSpAddressReference    theAddress;
  233. Str31                name;
  234. Str31                password;
  235. OSStatus            status;
  236. Boolean             OKHit = true;
  237.     
  238.     GetChooserName(name);
  239.     password[0] = 0;
  240.     
  241.     gIAmHost = false;
  242.     
  243.     theAddress = NSpDoModalJoinDialog(kNBPType, kJoinDialogLabel, name, password, NULL);
  244.     if (theAddress == NULL)        // The user cancelled
  245.         return (false);
  246.         
  247.     status = NSpGame_Join(&gNetGame, theAddress, name, password, 0, NULL, 0, 0);
  248.     FAIL_OSSTATUS(status, "NSpGame_Join returned an error");
  249.     
  250.     gNetState = kJoining;
  251.  
  252.     OKHit = WaitForAllPlayers();
  253.     if (OKHit == false)
  254.     {
  255.         gNetState = kSlacking;
  256.         ShutdownNetworking();
  257.     }
  258.     
  259.     return OKHit;
  260.     
  261. error:
  262.     return (false);
  263. }
  264.  
  265. //•    --------------------    HandleNetworking
  266.  
  267. void
  268. HandleNetworking(void)
  269. {
  270. NSpMessageHeader    *theMessage;
  271.     
  272.     if (gNetGame == NULL)
  273.         return;
  274.  
  275.     theMessage = NSpMessage_Get(gNetGame);
  276.     if (theMessage != NULL)
  277.     {
  278.         DoHandleMessage(theMessage);
  279.         NSpMessage_Release(gNetGame, theMessage);
  280.     }
  281. }
  282.  
  283. //•    --------------------    DoHandleMessage
  284.  
  285. static void
  286. DoHandleMessage(NSpMessageHeader *inMessage)
  287. {
  288.     switch (inMessage->what)
  289.     {
  290.         case kNSpPlayerJoined:
  291.             break;
  292.             
  293.         case kNSpPlayerLeft:
  294.             break;
  295.             
  296.         case kChatTextMessage:
  297.             DoHandleChatTextMessage((ChatTextMessage *)inMessage, nil);
  298.             break;
  299.             
  300.         case kStartGameMessage:
  301.             DoHandleStartGame((StartGameMessage *) inMessage);
  302.             break;
  303.             
  304.         case kInputMessage:
  305.             DoHandlePlayerInput((PlayerInputMessage *) inMessage);
  306.             break;
  307.             
  308.         case kEndGameMessage:
  309.             DoHandleEndGameMessage();
  310.             break;
  311.             
  312.         default:
  313.             break;
  314.     }
  315. }
  316.  
  317. //•    --------------------    WatchForPlayers
  318.  
  319. static void
  320. WatchForPlayers(DialogPtr dialog)
  321. {
  322. NSpMessageHeader    *theMessage;
  323.     
  324.     if (gNetGame == NULL)
  325.         return;
  326.  
  327.     while ((theMessage = NSpMessage_Get(gNetGame)) != NULL)
  328.     {
  329.         if (theMessage->what == kNSpPlayerJoined)
  330.         {
  331.             if (gNetState == kHosting)
  332.             {
  333.                 SendWelcomeMessage(((NSpPlayerJoinedMessage *)theMessage)->playerInfo.id);
  334.             }
  335.             
  336.             MakePlayerList(dialog);    
  337.         }
  338.         else if (theMessage->what == kNSpPlayerLeft) 
  339.         {
  340.             MakePlayerList(dialog);    
  341.         }
  342.         else if (theMessage->what == kChatTextMessage)
  343.         {
  344.             DoHandleChatTextMessage((ChatTextMessage *)theMessage, dialog);
  345.         }
  346.         else
  347.             DoHandleMessage(theMessage);
  348.             
  349.         NSpMessage_Release(gNetGame, theMessage);
  350.     }
  351. }
  352.  
  353. //•    --------------------    SendWelcomeMessage
  354.  
  355. static OSStatus
  356. SendWelcomeMessage(NSpPlayerID inID)
  357. {
  358. #pragma unused (inID)
  359. OSStatus    status = noErr;
  360.     
  361.     return (status);
  362. }
  363.  
  364. #pragma mark === Dialog Manager Cruft
  365.  
  366. //•    --------------------    SetDialogtemUserProc
  367.  
  368. static void
  369. SetDialogtemUserProc(DialogPtr dialog, SInt16 item, UserItemUPP theProc)
  370. {
  371. Rect     r;
  372. SInt16    itemType;
  373. Handle    itemH;
  374.  
  375.     GetDialogItem(dialog, item, &itemType, &itemH, &r);
  376.     itemH = (Handle) theProc;
  377.     SetDialogItem(dialog, item, itemType, itemH, &r);
  378. }
  379.  
  380. //•    --------------------    MakePlayerList
  381.  
  382. static void
  383. MakePlayerList(DialogPtr dialog)
  384. {
  385. SInt16                    i;
  386. Cell                    theCell;
  387. NSpPlayerEnumerationPtr    players;
  388. OSStatus                status;
  389. DialogInfo                *theInfo = (DialogInfo *) GetWRefCon(dialog);
  390. ListHandle                theList = theInfo->playerList;
  391.  
  392.  
  393.     LSetDrawingMode(true, theList);                            // turn on updating
  394.     status = NSpPlayer_GetEnumeration(gNetGame, &players);
  395.     FAIL_OSSTATUS(status, "NSpPlayer_GetEnumeration returned an error");
  396.         
  397.     for (i = 0; i < players->count; i++)
  398.     {
  399.         CopyPStr(players->playerInfo[i]->name, theInfo->nameListBuffer[i]);
  400.     }
  401.  
  402.     /* DELETE ALL EXISTING ROWS IN LIST */
  403.     LDelRow(0, 0, theList);
  404.  
  405.     /* ADD NAMES TO LIST */
  406.     if (players->count > 0)
  407.         LAddRow(players->count, 0, theList);        // create rows
  408.  
  409.     for (i = 0; i < players->count; i++)
  410.     {
  411.         theCell.h = 0;
  412.         theCell.v = i;
  413.         LSetCell(&theInfo->nameListBuffer[i][1], theInfo->nameListBuffer[i][0], theCell, theList);
  414.     }
  415.  
  416.     NSpPlayer_ReleaseEnumeration(gNetGame, players);
  417.     
  418. error:
  419.     return;
  420. }
  421.  
  422. //•    --------------------    WaitForAllPlayers
  423.  
  424. Boolean
  425. WaitForAllPlayers(void)
  426. {
  427. DialogPtr    theDialog = GetNewDialog(kWaitForPlayersDialogID, NULL, (WindowPtr) -1);
  428. ListHandle    playerList;
  429. SInt16         itemHit;
  430. Boolean     okHit = false;
  431. Rect         r, dataBounds = {0,0,0,1};
  432. Point        cellSize = {0,0};
  433. SInt16        itemType;
  434. Handle        itemH;
  435. DialogInfo    info;
  436. TextStyle    theStyle;
  437.     
  438.     ModalFilterUPP theFilter = NewModalFilterProc(DialogEventFilter);
  439.     UserItemUPP playerListProc = NewUserItemProc(PlayerListProc);
  440.     UserItemUPP chatViewProc = NewUserItemProc(ChatViewProc);
  441.     
  442.     // NOTE: check okUserItemProcUPP != NULL
  443.     
  444.     if (theDialog == NULL)
  445.         return (false);
  446.     
  447.     SetPort(theDialog);
  448.     SetDialogDefaultItem(theDialog, kOKButton);
  449.     SetDialogCancelItem(theDialog, kCancelButton);
  450.  
  451.     SetDialogtemUserProc(theDialog, kPlayerList, playerListProc);
  452.     SetDialogtemUserProc(theDialog, kChatWindow, chatViewProc);
  453.  
  454.     //    Now create the list of players
  455.     GetDialogItem(theDialog, kPlayerList, &itemType, &itemH, &r);
  456.     r.right -= 15;
  457.     
  458.     playerList = LNew(&r, &dataBounds, cellSize, 0, theDialog, true,
  459.                     false, false, true);
  460.     
  461.     info.playerList = playerList;
  462.  
  463.     //    Set up the text edut stuff
  464.     GetDialogItem(theDialog, kChatWindow, &itemType, &itemH, &r);
  465.     InsetRect(&r, 2, 2);
  466.     
  467.     info.teHandle = TEStyleNew(&r, &r);
  468.     TEAutoView(true, info.teHandle);
  469.  
  470.     //    Set up the default drawing info
  471.     theStyle.tsFont = kFontIDMonaco;
  472.     theStyle.tsSize = 9;
  473.     theStyle.tsColor.red = 0;
  474.     theStyle.tsColor.green = 0;
  475.     theStyle.tsColor.blue = 0;
  476.     theStyle.tsFace = normal;
  477.     TESetStyle(doAll, &theStyle, true, info.teHandle);
  478.     
  479.     //    If we're the joiner, disable the OK button
  480.     if (gNetState == kJoining)
  481.         DisableDialogItem(theDialog, kOKButton);
  482.     
  483.     //    Save our custom stuff in the refcon
  484.     SetWRefCon(theDialog, (SInt32) &info);
  485.     
  486.     ShowWindow(theDialog);
  487.     
  488.     do
  489.     {
  490.         ModalDialog(theFilter, &itemHit);
  491.     } while (itemHit != kOKButton && itemHit != kCancelButton);
  492.     
  493.     LDispose(playerList);
  494.     DisposeDialog(theDialog);
  495.     DisposeRoutineDescriptor(theFilter);
  496.     DisposeRoutineDescriptor(playerListProc);
  497.     DisposeRoutineDescriptor(chatViewProc);
  498.     
  499.     okHit = (itemHit == kOKButton || gNetState == kRunning);
  500.  
  501.     return (okHit);
  502. }
  503.  
  504. //•    --------------------    DisableDialogItem
  505.  
  506. static void
  507. DisableDialogItem(DialogPtr theDialog, SInt16 theItem)
  508. {
  509. SInt16    theType;
  510. Rect    theRect;
  511. Handle    theHandle;
  512.  
  513.     if (! theDialog)
  514.         return;
  515.  
  516.     GetDialogItem(theDialog, theItem, &theType, &theHandle, &theRect);
  517.  
  518.     if (! theHandle)
  519.         return;
  520.  
  521.     HiliteControl((ControlHandle) theHandle, 255);
  522.     theType |= kItemDisableBit;
  523.     SetDialogItem(theDialog, theItem, theType, theHandle, &theRect);
  524. }
  525.  
  526. #pragma mark === Callback Procs ===
  527.  
  528. //•    --------------------    PlayerListProc
  529.  
  530. static pascal void
  531. PlayerListProc(WindowPtr dialog, SInt16 itemNo)
  532. {
  533. Rect         r;
  534. SInt16        itemType;
  535. Handle        item;
  536. GrafPtr        theWindow = (GrafPtr) dialog;
  537. DialogInfo    *theInfo = (DialogInfo *)GetWRefCon(dialog);
  538. ListHandle    list = theInfo->playerList;
  539.  
  540.     if (itemNo == kPlayerList)
  541.     {    
  542.         GetDialogItem(dialog, itemNo, &itemType, &item, &r);
  543.         InsetRect(&r, -1, -1);
  544.         FrameRect(&r);
  545.         LUpdate(theWindow->visRgn, list);
  546.     }
  547. }
  548.  
  549. //•    --------------------    ChatViewProc
  550.  
  551. static pascal void
  552. ChatViewProc(WindowPtr dialog, SInt16 itemNo)
  553. {
  554. Rect         r;
  555. SInt16        itemType;
  556. Handle        item;
  557. DialogInfo *theInfo;
  558.     
  559.     GetDialogItem(dialog, itemNo, &itemType, &item, &r);
  560.     theInfo = (DialogInfo *)GetWRefCon(dialog);
  561.  
  562.     FrameRect(&r);
  563.     InsetRect(&r, 2, 2);
  564.     TEUpdate(&r, theInfo->teHandle);
  565.     
  566. }
  567.  
  568. //•    --------------------    DialogEventFilter
  569.  
  570. static pascal Boolean
  571. DialogEventFilter(DialogPtr dialog, EventRecord *event, SInt16 *itemHit)
  572. {
  573. OSErr                err;
  574. CGrafPtr            oldPort;
  575. GDHandle            oldGD;
  576. WindowRef            window;
  577. ModalFilterUPP        modalProc;
  578. Rect                itemRect;
  579. SInt16                key;
  580. SInt16                thePart;
  581. Boolean                accepted = false;
  582. Point theP;
  583. Boolean                hit;
  584. DialogInfo            *theInfo;
  585.     
  586.     GetGWorld(&oldPort, &oldGD);
  587.     SetGWorld((CGrafPtr)dialog, nil);
  588.  
  589.     WatchForPlayers(dialog);
  590.     if (gNetState == kRunning)
  591.     {
  592.         *itemHit = kOKButton;
  593.         return (true);
  594.     }
  595.  
  596.     switch(event->what) 
  597.     {
  598.         case keyDown:
  599.         case autoKey:
  600.             key = event->message & charCodeMask;
  601.             if (key == 0x0D)
  602.             {
  603.                 SendText(dialog);
  604.                 accepted = true;
  605.             }
  606.             else
  607.                 accepted = false;
  608.                 
  609.             break;
  610.     
  611.         case updateEvt:
  612.             if (event->message == (SInt32)dialog) 
  613.             {
  614.                 // in case a screen saver activates.
  615.                 UpdateDialog(dialog, dialog->visRgn);
  616.  
  617.                 SetCursor(&qd.arrow);
  618.             }    
  619.             break;
  620.  
  621.         case activateEvt:
  622.             accepted = true;
  623.             break;
  624.             
  625.         case mouseDown:    
  626.             thePart = FindWindow(event->where,&window);
  627.     
  628.             switch (thePart) 
  629.             {
  630.                 case inContent:
  631.                     theP = event->where;
  632.                     GlobalToLocal(&theP);
  633.  
  634.                     theInfo = (DialogInfo *)GetWRefCon(dialog);
  635.                     itemRect = (*theInfo->playerList)->rView;
  636.                     
  637.                     // add the scroll bar back in for hit testing (remember we took it out earlier)
  638.                     itemRect.right += 16;
  639.                     
  640.                     // See if they clicked in our list!
  641.                     if (PtInRect(theP, &itemRect))
  642.                     {
  643.                         hit = LClick(theP, nil, theInfo->playerList);
  644.                         // if they double-clicked the list, return 1, as if the OK button had been pressed
  645.                         if (hit)
  646.                             *itemHit = kOKButton;
  647.                         else
  648.                             *itemHit = kPlayerList;
  649.                         
  650.                         // tell the Dialog Manager that we handled this click, it can stop searching for a click-owner
  651.                         accepted = true;
  652.                     }
  653.                     break;
  654.     
  655.                 case inSysWindow:
  656.                     SysBeep(30);
  657.                     break;
  658.     
  659.                 case inDrag:
  660.                     if (window == dialog) 
  661.                     {
  662.                         DragWindow(dialog, event->where,&qd.screenBits.bounds);
  663.                         accepted = true;
  664.                     }
  665.                     break;
  666.             }
  667.             break;        
  668.     }
  669.     
  670.     if (! accepted) 
  671.     {
  672.         err = GetStdFilterProc(&modalProc);
  673.         if (err == noErr)
  674.             accepted = CallModalFilterProc(modalProc, dialog, event, itemHit);
  675.     }
  676.     
  677.     SetGWorld(oldPort, oldGD);
  678.  
  679.     return (accepted);
  680.  
  681. }
  682.  
  683. //•    --------------------    SendText
  684.  
  685. static void
  686. SendText(DialogPtr dialog)
  687. {
  688. Rect     r;
  689. SInt16    itemType;
  690. Handle    item;
  691. Str255    theText;
  692.     
  693.     GetDialogItem(dialog, kChatTextEntry, &itemType, &item, &r);
  694.     GetDialogItemText(item, theText);
  695.     SetDialogItemText(item, "\p");
  696.     
  697.     if (theText[0] > 0)
  698.         SendChatText(theText, kNSpAllPlayers);
  699.  
  700. }
  701.  
  702. #pragma mark =====
  703.  
  704. //•    --------------------    SendChatText
  705.  
  706. static void
  707. SendChatText(StringPtr inText, NSpPlayerID inTo)
  708. {
  709. ChatTextMessage    theMessage;
  710. OSStatus         status;
  711.     
  712.     theMessage.h.to = inTo;
  713.     theMessage.h.what = kChatTextMessage;
  714.     theMessage.h.messageLen = sizeof(ChatTextMessage);
  715.     CopyPStr(inText, theMessage.text);
  716.     
  717.     status = NSpMessage_Send(gNetGame, &theMessage.h, kNSpSendFlag_Junk | kNSpSendFlag_SelfSend);
  718. }
  719.  
  720. //•    --------------------    SendStartGame
  721.  
  722. void
  723. SendStartGame(void)
  724. {
  725. StartGameMessage    theMessage;
  726. OSStatus            status;
  727.     
  728.     NSpClearMessageHeader(&theMessage.h);
  729.     theMessage.h.to = kNSpAllPlayers;
  730.     theMessage.h.what = kStartGameMessage;
  731.     theMessage.h.messageLen = sizeof(StartGameMessage);
  732.     theMessage.seed = qd.randSeed;
  733.     
  734.     status = NSpMessage_Send(gNetGame, &theMessage.h, kNSpSendFlag_Registered | kNSpSendFlag_SelfSend);
  735. }
  736.  
  737. //•    --------------------    SendInputState
  738.  
  739. void
  740. SendInputState(Boolean left, Boolean right, Boolean fire)
  741. {
  742. PlayerInputMessage    theMessage;
  743. OSStatus    status;
  744.     
  745.     NSpClearMessageHeader(&theMessage.h);
  746.     theMessage.h.to = kNSpAllPlayers;
  747.     theMessage.h.what = kInputMessage;
  748.     theMessage.h.messageLen = sizeof(PlayerInputMessage);
  749.     theMessage.left = left;
  750.     theMessage.right = right;
  751.     theMessage.fire = fire;
  752.  
  753.     status = NSpMessage_Send(gNetGame, &theMessage.h, kNSpSendFlag_Registered);
  754. }
  755.  
  756. //•    --------------------    SendEndGame
  757.  
  758. void
  759. SendEndGame(void)
  760. {
  761. OSStatus    status;
  762. NSpMessageHeader theMessage;
  763.     
  764.     NSpClearMessageHeader(&theMessage);
  765.     theMessage.to = kNSpAllPlayers;
  766.     theMessage.what = kEndGameMessage;
  767.     theMessage.messageLen = sizeof(NSpMessageHeader);
  768.     
  769.     status = NSpMessage_Send(gNetGame, &theMessage, kNSpSendFlag_Registered);
  770. }
  771.  
  772. //•    --------------------    DoHandleChatTextMessage
  773.  
  774. static void
  775. DoHandleChatTextMessage(ChatTextMessage *inMessage, DialogPtr dialog)
  776. {
  777. DialogInfo    *theInfo;
  778.     
  779.     if (! dialog)
  780.         return;
  781.         
  782.     theInfo = (DialogInfo *)GetWRefCon(dialog);
  783.     PrintPlayerText(inMessage->text, inMessage->h.from, theInfo->teHandle);
  784. }
  785.  
  786. //•    --------------------    DoHandleStartGame
  787.  
  788. static void
  789. DoHandleStartGame(StartGameMessage *inMessage)
  790. {
  791.     gNetState = kRunning;
  792.     qd.randSeed = inMessage->seed;
  793. }
  794.  
  795. //•    --------------------    DoHandlePlayerInput
  796.  
  797. static void
  798. DoHandlePlayerInput(PlayerInputMessage *inMessage)
  799. {
  800.     if (gIAmHost)
  801.     {
  802.         gGameKeys.redLeft = inMessage->left;
  803.         gGameKeys.redRight = inMessage->right;
  804.         gGameKeys.redFire = inMessage->fire;
  805.     }
  806.     else
  807.     {
  808.         gGameKeys.greenLeft = inMessage->left;
  809.         gGameKeys.greenRight = inMessage->right;
  810.         gGameKeys.greenFire = inMessage->fire;
  811.     }    
  812.     gReceivedInput = true;
  813. }
  814.  
  815. //•    --------------------    DoHandleEndGameMessage
  816.  
  817. static void
  818. DoHandleEndGameMessage(void)
  819. {
  820.     gGotEndGameMessage = true;
  821. }
  822.  
  823. //•    --------------------    PrintPlayerText
  824.  
  825. static void
  826. PrintPlayerText(StringPtr inText, NSpPlayerID inPlayer, TEHandle inTEHandle)
  827. {
  828. NSpPlayerInfoPtr    info;
  829.     
  830.     NSpPlayer_GetInfo(gNetGame, inPlayer, &info);
  831.     
  832.     TEInsert(&info->name[1], info->name[0], inTEHandle);
  833.     TEInsert(&kSeparatorString[1], kSeparatorString[0], inTEHandle);
  834.     TEInsert(&inText[1], inText[0], inTEHandle);
  835.     TEInsert(&kReturn, 1, inTEHandle);
  836.  
  837.     //•    Select end of the TE text
  838.     TESetSelect(32767L, 32767L, inTEHandle);
  839.  
  840.     //•    Scroll it into view if necessary
  841.     TESelView(inTEHandle);
  842. }
  843.