Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
NetStuff.cp
/* |
File: NetStuff.cp |
Contains: xxx put contents here xxx |
Version: xxx put version here xxx |
Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
File Ownership: |
DRI: xxx put dri here xxx |
Other Contact: xxx put other contact here xxx |
Technology: xxx put technology here xxx |
Writers: |
(cjd) Chris De Salvo |
Change History (most recent first): |
<SP8> 3/9/99 cjd Added new enumerations depending on whether you're the client or |
the host. |
*/ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ |
//¥ Copyright © 1996, 1997 Apple Computer, Inc., All Rights Reserved |
//¥ |
//¥ |
//¥ You may incorporate this sample code into your applications without |
//¥ restriction, though the sample code has been provided "AS IS" and the |
//¥ responsibility for its operation is 100% yours. However, what you are |
//¥ not permitted to do is to redistribute the source as "DSC Sample Code" |
//¥ after having made changes. If you're going to re-distribute the source, |
//¥ we require that you make it clear in the source that the code was |
//¥ descended from Apple Sample Code, but that you've made changes. |
//¥ |
//¥ Authors: |
//¥ Jamie Osborne |
//¥ Chris De Salvo |
//¥ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ ------------------------------ Includes |
#include <Fonts.h> |
#include <MacWindows.h> |
#include <Menus.h> |
#include <OpenTptInternet.h> |
#include <Resources.h> |
#include <TextUtils.h> |
#include "NetStuff.h" |
#include <PLStringFuncs.h> |
#include <stdio.h> |
#include <string.h> |
//¥ ------------------------------ Private Definitions |
//¥ If this is set to 1 then the player enumeration menu item iterates by calling NSpPlayer_GetInfo |
//¥ rather than using the data in the PlayerEnumeration data structure. This is merely for coverage |
//¥ testing of the GetInfo call on the client side. |
#define USE_PLAYER_GET_INFO 1 |
//¥ ------------------------------ Private Types |
enum |
{ |
kStandardMessageSize = 1500, |
kBufferSize = 0, |
kQElements = 0, |
kTimeout = 5000, |
kMaxPlayers = 8 |
}; |
//¥ ------------------------------ Private Variables |
static Str31 gameName; |
static Str31 password; |
static Str31 playerName; |
static Str31 kJoinDialogLabel = "\pChoose a Game:"; |
static Boolean gInCallback = false; |
static UInt32 gLastUpdate = 0; |
static UInt32 gUpdateFrequency = 2; |
static PlayerInputMessage gPlayerMessage; |
static UInt32 gPlayerMessageSize = 400; |
static GameStateMessage gGameStateMessage; |
static UInt32 gGameStateMessageSize = 1024; |
static UInt32 gSendOptions = kNSpSendFlag_Normal; |
static UInt32 gHostSendOptions = kNSpSendFlag_Registered | kNSpSendFlag_SelfSend; |
static MenuHandle gHostMenuH; |
static UInt32 gHostUpdateFrequency = 2; |
static UInt32 gLastHostUpdate = 0; |
static WindowStuff gWindowStuff[8]; |
static NSpPlayerID gMyPlayerID = 0; |
static Str255 gContextString = "\pNetSprocket Test Context!!"; |
//¥ ------------------------------ Private Functions |
static WindowStuff *GetFreeWindowStuff(void); |
static void ReleaseWindowStuff(WindowStuff *inStuff); |
static WindowStuff *GetPlayersWindowStuff(NSpPlayerID inPlayer); |
static WindowPtr FindPlayersWindow(NSpPlayerID inPlayer); |
static void InvalPlayerWindow(NSpPlayerID inPlayer); |
static pascal Boolean MessageHandler(NSpGameReference inGameRef, NSpMessageHeader *inMessage, void *inContext); |
static void InitNetMenu(MenuHandle menu); |
static void GetChooserName(Str255 name); |
static void CloseAllWindows(void); |
static void AddHostMenu(void); |
static void DoAdjustMenu(MenuRef m, UInt32 options, UInt32 updateFrequency, UInt32 messageSize); |
static void DoSendLeaveMessage(NSpPlayerID inID); |
static void DoHandleMessage(NSpMessageHeader *inMessage); |
static void GetMessages(void); |
static void UpdateNetWindows(void); |
static void GetInfoEnumeratePlayers(void); |
static void EnumeratePlayers(void); |
//¥ ------------------------------ Public Variables |
Boolean gHost = false; |
NSpGameReference gNetGame = nil; |
//¥ -------------------- GetFreeWindowStuff |
// this is not reentrant |
static WindowStuff * |
GetFreeWindowStuff(void) |
{ |
for (int i = 0; i < 8; i++) |
{ |
if (gWindowStuff[i].id == 0) |
return &gWindowStuff[i]; |
} |
return nil; |
} |
//¥ -------------------- ReleaseWindowStuff |
static void |
ReleaseWindowStuff(WindowStuff *inStuff) |
{ |
if (inStuff == nil) |
printf("passed in nill stuff pointer!\n"); |
else |
memset(inStuff, 0, sizeof(WindowStuff)); |
} |
//¥ -------------------- GetPlayersWindowStuff |
static WindowStuff * |
GetPlayersWindowStuff(NSpPlayerID inPlayer) |
{ |
for (int i = 0; i < 8; i++) |
{ |
if (gWindowStuff[i].id == inPlayer) |
return &gWindowStuff[i]; |
} |
return nil; |
} |
//¥ -------------------- FindPlayersWindow |
//¥ |
//¥ Finds the window associated with the given player |
static WindowPtr |
FindPlayersWindow(NSpPlayerID inPlayer) |
{ |
WindowPtr w; |
WindowStuff *stuff; |
w = FrontWindow(); |
while (w != nil) |
{ |
stuff = (WindowStuff *) GetWRefCon(w); |
if (stuff->id == inPlayer) |
break; |
else |
w = GetNextWindow(w); |
} |
return w; |
} |
//¥ -------------------- InvalPlayerWindow |
static void |
InvalPlayerWindow(NSpPlayerID inPlayer) |
{ |
WindowPtr w = FindPlayersWindow(inPlayer); |
if (w) |
{ |
GrafPtr oldPort; |
GetPort(&oldPort); |
SetPort(w); |
InvalRect(&w->portRect); |
SetPort(oldPort); |
} |
} |
//¥ -------------------- MessageHandler |
//¥ |
//¥ this function gets called every time NetSprocket receives a new message. |
//¥ we use it to prevent our message q from getting too full if we don't idle enough |
//¥ a good example is when the user has clicked in the menu bar and is reading menus |
static pascal Boolean |
MessageHandler(NSpGameReference inGameRef, NSpMessageHeader *inMessage, void *inContext) |
{ |
gInCallback = true; |
// if it's a system message, just leave it in the q, so that we can handle it later (when we're |
// not at interrupt time) |
if (inMessage->what & kNSpSystemMessagePrefix) |
return true; // tells NetSprocket to put the message in the message Q |
else // it's one of ours |
{ |
if (inMessage->what == kPlayerInputMessage && gHost) |
{ |
WindowStuff *stuff = GetPlayersWindowStuff(inMessage->from); |
if (stuff) |
{ |
stuff->lastMessage = inMessage->id; |
stuff->changed = true; |
} |
return false; |
} |
else if (inMessage->what == kGameStateMessage && !gHost) |
{ |
WindowStuff *stuff = GetPlayersWindowStuff(gMyPlayerID); |
if (stuff) |
{ |
stuff->lastMessage = inMessage->id; |
stuff->changed = true; |
} |
return false; |
} |
} |
gInCallback = false; |
//¥ If it's some state we haven't considered then better leave it in the queue |
return (true); |
} |
//¥ -------------------- GetChooserName |
static void |
GetChooserName(Str255 name) |
{ |
StringHandle userName; |
userName = GetString(-16096); |
if (userName == nil) |
{ |
name[0] = 0; |
} |
else |
{ |
PLstrcpy(name, *userName); |
ReleaseResource ((Handle) userName); |
} |
} |
//¥ -------------------- RefreshWindow |
void |
RefreshWindow(WindowPtr inWindow) |
{ |
WindowStuff *stuff = (WindowStuff *) GetWRefCon(inWindow); |
if (stuff->lastMessage != 0) |
NumToString(stuff->lastMessage, stuff->text); |
EraseRect(&inWindow->portRect); |
MoveTo(20,20); |
DrawString(stuff->text); |
} |
//¥ -------------------- InitNetMenu |
static void |
InitNetMenu(MenuHandle menu) |
{ |
SetItemMark(menu, iJunk, noMark); |
SetItemMark(menu, iNormal, noMark); |
SetItemMark(menu, iRegistered, noMark); |
SetItemMark(menu, iBlocking, noMark); |
SetItemMark(menu, i1X, noMark); |
SetItemMark(menu, i10X, noMark); |
SetItemMark(menu, i30X, noMark); |
SetItemMark(menu, iNoLimit, noMark); |
SetItemMark(menu, iLess500, noMark); |
SetItemMark(menu, i1K, noMark); |
SetItemMark(menu, i10K, noMark); |
SetItemMark(menu, i100K, noMark); |
} |
//¥ -------------------- InitNetworking |
OSStatus |
InitNetworking(NSpGameID inGameID) |
{ |
OSStatus status; |
printf("Initializing NetSprocket... "); |
memset(gWindowStuff, 0, sizeof(WindowStuff) * 8); |
status = NSpInitialize(kStandardMessageSize, kBufferSize, kQElements, inGameID, kTimeout); |
if (status != noErr) |
printf("NSpInitialize returned error %d\n", status); |
else |
printf("Done\n"); |
// Install an async message handler. We do this so that we won't get hosed if we |
// don't call HandleNetworking often enough (such as a tight loop for mouse-down |
status = NSpInstallAsyncMessageHandler(MessageHandler, gContextString); |
if (status != noErr) |
printf("NSpInstallAsyncMessageHandler returned error %d\n", status); |
MenuHandle h = GetMenuHandle(131); |
if (h) |
InitNetMenu(h); |
return status; |
} |
//¥ -------------------- CloseAllWindows |
static void |
CloseAllWindows(void) |
{ |
WindowPtr w, nextWind; |
w = FrontWindow(); |
while (w != nil) |
{ |
nextWind = GetNextWindow(w); |
WindowStuff *stuff = (WindowStuff *) GetWRefCon(w); |
if (stuff) |
{ |
DisposePtr((Ptr) stuff); |
DisposeWindow(w); |
} |
w = nextWind; |
} |
} |
//¥ -------------------- ShutdownNetworking |
void |
ShutdownNetworking(void) |
{ |
OSStatus status; |
if (gNetGame) |
{ |
status = NSpGame_Dispose( gNetGame, 0 ); |
if (status != noErr) |
{ |
printf("NSpGame_Dispose returned error %d\n", status); |
// I REALLY want it to shutdown |
status = NSpGame_Dispose( gNetGame, kNSpGameFlag_ForceTerminateGame ); |
if (status != noErr) |
printf("NSpGame_Dispose (force) returned error %d\n", status); |
} |
if (gHost) |
{ |
DeleteMenu(132); |
ReleaseResource((Handle) gHostMenuH); |
DrawMenuBar(); |
} |
gNetGame = NULL; |
} |
// if there are any windows left, kill them |
CloseAllWindows(); |
} |
//¥ -------------------- AddHostMenu |
static void |
AddHostMenu(void) |
{ |
gHostMenuH = GetMenu(132); |
if (gHostMenuH == nil) |
DebugStr("\pCouldn't find menu resource!"); |
else |
InsertMenu(gHostMenuH, 0); |
InitNetMenu(gHostMenuH); |
DrawMenuBar(); |
} |
//¥ -------------------- HandleNetMenuChoice |
void |
HandleNetMenuChoice(short menu, short item) |
{ |
MenuHandle h = GetMenuHandle(menu); |
UInt32 *options; |
UInt32 *frequency; |
UInt32 *size; |
if (menu == 132) // host menu |
{ |
options = &gHostSendOptions; |
frequency = &gHostUpdateFrequency; |
size = &gGameStateMessageSize; |
} |
else |
{ |
options = &gSendOptions; |
frequency = &gUpdateFrequency; |
size = &gPlayerMessageSize; |
} |
switch(item) |
{ |
case iJunk: |
*options &= 0xFF0FFFFF; |
*options |= kNSpSendFlag_Junk; |
break; |
case iNormal: |
*options &= 0xFF0FFFFF; |
*options |= kNSpSendFlag_Normal; |
break; |
case iRegistered: |
*options &= 0xFF0FFFFF; |
*options |= kNSpSendFlag_Registered; |
break; |
case iBlocking: |
if (*options & kNSpSendFlag_Blocking) |
*options &= ~kNSpSendFlag_Blocking; |
else |
*options |= kNSpSendFlag_Blocking; |
break; |
case i1X: |
*frequency = 60; |
break; |
case i10X: |
*frequency = 6; |
break; |
case i30X: |
*frequency = 2; |
break; |
case iNoLimit: |
*frequency = 0; |
break; |
case iLess500: |
*size = 400; |
break; |
case i1K: |
*size = 1024; |
break; |
case i10K: |
*size = 10240; |
break; |
case i100K: |
*size = 102400; |
break; |
case iEnumerate: |
#if USE_PLAYER_GET_INFO |
if (131 != menu) |
GetInfoEnumeratePlayers(); |
else |
#endif |
EnumeratePlayers(); |
break; |
default: |
break; |
} |
} |
//¥ -------------------- DoAdjustMenu |
static void |
DoAdjustMenu(MenuRef m, UInt32 options, UInt32 updateFrequency, UInt32 messageSize) |
{ |
if (options & kNSpSendFlag_Junk) |
SetItemMark(m, iJunk, checkMark); |
else |
SetItemMark(m, iJunk, noMark); |
if (options & kNSpSendFlag_Normal) |
SetItemMark(m, iNormal, checkMark); |
else |
SetItemMark(m, iNormal, noMark); |
if (options & kNSpSendFlag_Registered) |
SetItemMark(m, iRegistered, checkMark); |
else |
SetItemMark(m, iRegistered, noMark); |
if (options & kNSpSendFlag_Blocking) |
SetItemMark(m, iBlocking, checkMark); |
else |
SetItemMark(m, iBlocking, noMark); |
SetItemMark(m, i1X, noMark); |
SetItemMark(m, i10X, noMark); |
SetItemMark(m, i30X, noMark); |
SetItemMark(m, iNoLimit, noMark); |
switch(updateFrequency) |
{ |
case 60: |
SetItemMark(m, i1X, checkMark); |
break; |
case 6: |
SetItemMark(m, i10X, checkMark); |
break; |
case 2: |
SetItemMark(m, i30X, checkMark); |
break; |
default: |
SetItemMark(m, iNoLimit, checkMark); |
break; |
} |
SetItemMark(m, iLess500, noMark); |
SetItemMark(m, i1K, noMark); |
SetItemMark(m, i10K, noMark); |
SetItemMark(m, i100K, noMark); |
switch(messageSize) |
{ |
case 400: |
SetItemMark(m, iLess500, checkMark); |
break; |
case 1024: |
SetItemMark(m, i1K, checkMark); |
break; |
case 10240: |
SetItemMark(m, i10K, checkMark); |
break; |
case 102400: |
SetItemMark(m, i100K, checkMark); |
break; |
} |
} |
//¥ -------------------- AdjustNetMenus |
void |
AdjustNetMenus(void) |
{ |
MenuRef m = GetMenu(131); |
DoAdjustMenu(m, gSendOptions, gUpdateFrequency, gPlayerMessageSize); |
if (gHost) |
{ |
m = GetMenu(132); |
if (m) |
DoAdjustMenu(m, gHostSendOptions, gHostUpdateFrequency, gGameStateMessageSize); |
} |
} |
//¥ -------------------- DoHost |
OSStatus |
DoHost(void) |
{ |
OSStatus status; |
Str255 chooserName; |
NSpProtocolListReference theList = NULL; |
Boolean okHit; |
// Create an empty protocol list |
status = NSpProtocolList_New(NULL, &theList); |
if (status != noErr) |
{ |
printf("NSpProtocolList_New returned error: %d\n", status); |
goto failure; |
} |
// Now present a UI for the hosting |
// Note! Do NOT pass in string constants, as the user can change these values |
GetChooserName(chooserName); |
PLstrncpy(playerName, chooserName, 31); |
PLstrcpy(gameName, "\pNetSprocket Test"); |
password[0] = 0; |
okHit = NSpDoModalHostDialog(theList, gameName, playerName, password, nil); |
if (!okHit) |
{ |
status = kUserCancelled; |
goto failure; |
} |
// Now host the game |
status = NSpGame_Host(&gNetGame, theList, kMaxPlayers, gameName, |
password, playerName, 0, kNSpClientServer, 0); |
if (status != noErr) |
{ |
printf("NSpGame_Host returned error %d\n", status); |
goto failure; |
} |
gHost = true; |
if (status == noErr) |
AddHostMenu(); |
return status; |
failure: |
if (theList != nil) |
NSpProtocolList_Dispose(theList); |
return status; |
} |
//¥ -------------------- DoJoin |
OSStatus |
DoJoin(void) |
{ |
NSpAddressReference theAddress; |
OSStatus status; |
Str255 chooserName; |
GetChooserName(chooserName); |
PLstrncpy(playerName, chooserName, 31); |
password[0] = 0; |
// Present the UI for joining a game |
// passing an empty string (not nil) for the type causes NetSprocket to use |
// the game id passed in to initialize |
theAddress = NSpDoModalJoinDialog("\p", kJoinDialogLabel, playerName, password, NULL); |
if (theAddress == NULL) // The user cancelled |
return kUserCancelled; |
status = NSpGame_Join(&gNetGame, theAddress, playerName, password, 0, NULL, 0, 0); |
if (status != noErr) |
printf("NSpGame_Join returned error %d\n", status); |
else |
gHost = false; |
return status; |
} |
//¥ -------------------- DoSendLeaveMessage |
static void |
DoSendLeaveMessage(NSpPlayerID inID) |
{ |
NSpMessageHeader m; |
OSStatus status; |
NSpClearMessageHeader(&m); |
m.what = kLeaveMessage; |
m.to = inID; |
m.messageLen = sizeof(NSpMessageHeader); |
status = NSpMessage_Send(gNetGame, &m, kNSpSendFlag_Registered); |
} |
//¥ -------------------- DoCloseNetWindow |
void |
DoCloseNetWindow(WindowPtr inWindow) |
{ |
if (gHost) |
{ |
WindowStuff *stuff = (WindowStuff *) GetWRefCon(inWindow); |
DoSendLeaveMessage(stuff->id); |
} |
else |
ShutdownNetworking(); |
} |
//¥ -------------------- DoHandleMessage |
static void |
DoHandleMessage(NSpMessageHeader *inMessage) |
{ |
switch (inMessage->what) |
{ |
case kLeaveMessage: |
printf("Got a message telling us to leave the game."); |
ShutdownNetworking(); |
break; |
case kNSpPlayerJoined: |
{ |
NSpPlayerJoinedMessage *theMessage = (NSpPlayerJoinedMessage *) inMessage; |
printf("Got player joined message: %d\n", theMessage->playerInfo.id); |
if (gHost || theMessage->playerInfo.id == NSpPlayer_GetMyID(gNetGame)) |
{ |
gMyPlayerID = NSpPlayer_GetMyID(gNetGame); |
WindowPtr wind = GetNewCWindow(128, nil, (WindowPtr) -1L); |
if (!wind) |
printf("Failed to create a new window!\n"); |
else |
{ |
WindowStuff *stuff = GetFreeWindowStuff(); |
if (stuff == nil) |
{ |
printf("Couldn't alloc memory to show window.\n"); |
DisposeWindow(wind); |
} |
else |
{ |
stuff->id = theMessage->playerInfo.id; |
stuff->lastMessage = 0; |
PLstrcpy(stuff->text, "\pNew Player"); |
SetWTitle(wind,theMessage->playerInfo.name); |
SetWRefCon(wind, (long) stuff); |
InvalPlayerWindow(stuff->id); |
} |
} |
} |
} |
break; |
case kNSpPlayerLeft: |
{ |
char name[32]; |
NSpPlayerLeftMessage *theMessage = (NSpPlayerLeftMessage *) inMessage; |
BlockMoveData(theMessage->playerName + 1, name, theMessage->playerName[0]); |
name[theMessage->playerName[0]] = '\0'; |
printf("Got player left message: %s, player #%d\n", name, theMessage->playerID); |
if (gHost) |
{ |
WindowPtr w = FindPlayersWindow(theMessage->playerID); |
if (w) |
{ |
WindowStuff *stuff = (WindowStuff *) GetWRefCon(w); |
ReleaseWindowStuff(stuff); |
DisposeWindow(w); |
} |
else |
printf("Didn't find the window for the player that left!!\n"); |
} |
} |
break; |
case kNSpGameTerminated: |
printf("Got Game terminated message\n"); |
ShutdownNetworking(); |
break; |
default: |
break; |
} |
} |
//¥ -------------------- GetMessages |
static void |
GetMessages(void) |
{ |
NSpMessageHeader *theMessage; |
do |
{ |
theMessage = NSpMessage_Get(gNetGame); |
DoHandleMessage(theMessage); |
NSpMessage_Release(gNetGame, theMessage); |
} while (gNetGame && theMessage != NULL); |
} |
//¥ -------------------- UpdateNetWindows |
static void |
UpdateNetWindows(void) |
{ |
WindowPtr w; |
w = FrontWindow(); |
while (w != nil) |
{ |
WindowStuff *stuff = (WindowStuff *) GetWRefCon(w); |
if (stuff && stuff->changed) |
{ |
GrafPtr oldPort; |
GetPort(&oldPort); |
SetPort(w); |
RefreshWindow(w); |
SetPort(oldPort); |
stuff->changed = false; |
} |
w = GetNextWindow(w); |
} |
} |
//¥ -------------------- HandleNetwork |
void |
HandleNetwork(void) |
{ |
OSStatus status; |
if (!gNetGame) |
return; |
GetMessages(); |
// update any windows as necessary |
UpdateNetWindows(); |
UInt32 time = TickCount(); |
if (gNetGame && time > gLastUpdate + gUpdateFrequency) |
{ |
NSpClearMessageHeader(&gPlayerMessage.h); |
gPlayerMessage.h.what = kPlayerInputMessage; |
gPlayerMessage.h.to = kNSpHostOnly; |
gPlayerMessage.h.messageLen = gPlayerMessageSize; |
// Send my info to the host |
status = NSpMessage_Send(gNetGame, &gPlayerMessage.h, gSendOptions); |
if (status != noErr) |
printf("NSpMessage_Send returned error: %d\n", status); |
if (gHost && time > gLastHostUpdate + gHostUpdateFrequency) |
{ |
NSpClearMessageHeader(&gGameStateMessage.h); |
gGameStateMessage.h.what = kGameStateMessage; |
gGameStateMessage.h.to = kNSpAllPlayers; |
gGameStateMessage.h.messageLen = gGameStateMessageSize; |
// Send my info to the host |
status = NSpMessage_Send(gNetGame, &gGameStateMessage.h, gHostSendOptions); |
if (status != noErr) |
printf("NSpMessage_Send returned error: %d\n", status); |
gLastHostUpdate = time; |
} |
gLastUpdate = time; |
} |
} |
//¥ -------------------- GetInfoEnumeratePlayers |
static void |
GetInfoEnumeratePlayers(void) |
{ |
OSStatus theErr; |
NSpPlayerEnumerationPtr thePlayers; |
UInt32 i; |
if (nil == gNetGame) |
{ |
printf("gNetGame is nil.\n"); |
return; |
} |
theErr = NSpPlayer_GetEnumeration(gNetGame, &thePlayers); |
if (noErr != theErr) |
{ |
printf("NSpPlayer_GetEnumeration returned %ld\n", theErr); |
return; |
} |
printf("PlayerID IP Address Name\n"); |
printf("-------- --------------- ----------------\n"); |
for (i = 0; i < thePlayers->count; i++) |
{ |
char name[sizeof (NSpPlayerName)]; |
NSpPlayerInfoPtr thePlayer; |
OTAddress *address; |
OSStatus theErr; |
NSpPlayer_GetInfo(gNetGame, thePlayers->playerInfo[i]->id, &thePlayer); |
BlockMoveData(thePlayer->name + 1, name, thePlayer->name[0]); |
name[thePlayer->name[0]] = '\0'; |
printf("%0.8ld ", thePlayer->id); |
theErr = NSpPlayer_GetAddress(gNetGame, thePlayer->id, &address); |
if ((noErr != theErr) || (NULL == address)) |
{ |
printf("Error %9ld", theErr); |
} |
else |
{ |
if (AF_INET == address->fAddressType) |
{ |
InetAddress *ip; |
ip = (InetAddress *) address; |
printf("%3d.%3d.%3d.%3d", |
(ip->fHost & 0xFF000000) >> 24, |
(ip->fHost & 0x00FF0000) >> 16, |
(ip->fHost & 0x0000FF00) >> 8, |
(ip->fHost & 0x000000FF) >> 0); |
} |
else |
{ |
printf("N/A - AppleTalk"); |
} |
} |
if (NULL != address) |
DisposePtr((Ptr) address); |
printf(" %s\n", name); |
} |
} |
//¥ -------------------- EnumeratePlayers |
static void |
EnumeratePlayers(void) |
{ |
OSStatus theErr; |
NSpPlayerEnumerationPtr thePlayers; |
UInt32 i; |
if (nil == gNetGame) |
printf("gNetGame is nil.\n"); |
theErr = NSpPlayer_GetEnumeration(gNetGame, &thePlayers); |
if (noErr != theErr) |
{ |
printf("NSpPlayer_GetEnumeration returned %ld\n", theErr); |
return; |
} |
printf("PlayerID Name\n"); |
printf("-------- -------------------------------\n"); |
for (i = 0; i < thePlayers->count; i++) |
{ |
char name[sizeof (NSpPlayerName)]; |
BlockMoveData(thePlayers->playerInfo[i]->name + 1, name, thePlayers->playerInfo[i]->name[0]); |
name[thePlayers->playerInfo[i]->name[0]] = '\0'; |
printf("%0.8ld %s\n", thePlayers->playerInfo[i]->id, name); |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14