home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include <stdio.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <errno.h>
- #include <string.h>
- #include <malloc.h>
- #include <bstring.h>
-
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <Xm/Xm.h>
- #include <Xm/List.h>
- #include <GL/GLwDrawA.h>
- #include "Row.h"
-
-
- #include "vroom.h"
- #include "server.h"
- #include "client.h"
- #include "multicast.h"
- #include "playmode.h"
- #include "track.h"
- #include "ogl.h"
- #include "solo.h"
- #include "sound.h"
- #include "messages.h"
-
- typedef void (*ClientFunc)( void ) ;
-
- #define CLIENT_ST_INIT 0
- #define CLIENT_ST_WAIT_TO_JOIN 1
- #define CLIENT_ST_SELECT_TRACK 2
-
- #define WAIT_TO_JOIN_DELAY (5.0f) /* seconds */
-
- typedef struct _serverHost {
- long id ;
- int nClients ;
- long status ;
- XmString name ;
- float nextDeadLine ;
- struct _serverHost *next ;
- } ServerHost ;
-
- /* BEGIN PROTOTYPES -S client.c */
- static ServerHost * addServerToList( long id, int n, long status ) ;
- static ServerHost * checkForNewHost( outStatusPacket *bp ) ;
- static void checkServers( void ) ;
- static void clientLoadCourse( long courseId ) ;
- static void clientNoOp( void ) ;
- static void clientPostRace( void ) ;
- static void clientPostTrial( void ) ;
- static void clientPreRace( void ) ;
- static void clientPreTrial( void ) ;
- static void clientRace( void ) ;
- static void clientSpectate( void ) ;
- static void clientTrial( void ) ;
- static void clientWaitToJoin( void ) ;
- static void closeOutput( void ) ;
- static int connectToServer( long id ) ;
- static XmString createServerListString( long id, int nClients,
- long status ) ;
- static void findSelf( long serverId, long playerId[] ) ;
- static ServerHost * findServer( long id ) ;
- static int processServerAckPacket( outAckPacket *packet,
- int size ) ;
- static int processServerCoursePacket( outCoursePacket *packet,
- int size ) ;
- static int processServerMsgPacket( outMsgPacket *packet,
- int size ) ;
- static int processServerNamePacket( outNamePacket *packet,
- int size ) ;
- static int processServerRacePacket( outRacePacket *packet,
- int size ) ;
- static int processServerStatusPacket( outStatusPacket *packet,
- int size ) ;
- static void removeServer( long id ) ;
- static void resetToServerSearch( void ) ;
- static void sendServerInfoPacket( int option, int choice ) ;
- static void sendServerNamePacket( void ) ;
- static void sendServerSpeedPacket( void ) ;
- static void serverSelectionCB( Widget w, Widget list,
- XtPointer callData ) ;
- static void serverStatsCB( Widget w, Widget list,
- XtPointer callData ) ;
- static void updateSpeed( void ) ;
- /* END PROTOTYPES -S client.c */
-
- char teamPosition[MAX_PLAYERS] ;
- int steering ;
- long gameServerId = 0 ;
-
- extern int debugOn ;
- extern int raceLaps ;
- extern int errno ;
- extern int h_errno ;
- extern int nTracks ;
- extern int nCars ;
- extern int startLastLap ;
- extern char *basename ;
- extern char *myName ;
- extern float currentTime ;
- extern float startSoundTime ;
- extern float speedFactor ;
- extern long myHostId ;
- extern Widget serverCourseForm ;
- extern Widget courseVoteForm ;
- extern Widget resultsForm ;
- extern Widget previewForm ;
- extern Widget serverForm ;
- extern Widget mainOgl ;
- extern int self ;
- extern PlayerStruct player[] ;
- extern Car cars[] ;
- extern Sfx collideSfx ;
- extern Sfx changeLaneSfx ;
- extern Sfx crashSfx ;
- extern Sfx lastlapSfx ;
- extern Sfx motorSfx ;
- extern Sfx squealSfx ;
- extern Sfx startSfx ;
- extern Sfx toneSfx ;
-
- static ServerHost *serverList = NULL ;
- static int nServers = 0 ;
- static int showRecord ;
- static Widget serverSelector ;
- static Widget serverSelectorList ;
- static int inFd ;
- static struct sockaddr_in inAddr ;
- static int outFd = -1 ;
- static struct sockaddr_in outAddr ;
- static int inputLength ;
- static int lookForSelf = 0 ;
- static Widget serverCourseSelector = NULL ;
- static float deadLineToServer = 0.0f ;
- static float nextDeadLine = 0.0f ;
- static float joinDeadLine = 0.0f ;
- static float joinServerTime = 0.0f ;
- static ClientFunc clientFunc ;
- static long loadedCourseId = -1 ;
- static outRacePacket racePacket ;
- static inSpeedPacket speedPacket ;
- static int newRacePacket = 0 ;
- static int checkIds = 0 ;
- static long serverStatus = 0 ;
- static int activePlayer = 0 ;
-
- static char *serverStatusString[] = {
- "initializing",
- "course selection",
- "loading course",
- "preparing time trials",
- "running time trials",
- "finishing time trials",
- "preparing to race",
- "running race",
- "finishing race",
- "showing race results",
- "quitting",
- } ;
-
-
- /*------------------------------------------------------------------------------
- * Make the chooser for selecting a server (team mode).
- *----------------------------------------------------------------------------*/
- void
- createServerSelector(
- Widget parent
- )
- {
- int n ;
- Arg args[10] ;
- Widget w ;
- Widget button[4] ;
- static char *labels[4] = { "Join", "Info", "Quit", "Help" } ;
- static int init = 0 ;
- static char *helpFiles[] = { "server.help", NULL } ;
-
- if( init )
- {
- return ;
- }
- init = 1 ;
-
- nServers = 0 ;
-
- n = 0 ;
- XtSetArg( args[n], XmNtopAttachment, XmATTACH_FORM ) ; n++ ;
- XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM ) ; n++ ;
- XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM ) ; n++ ;
- XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM ) ; n++ ;
- createSelectionList( "Select a game server:", parent,
- &serverSelectorList, 4, button, labels, args, n ) ;
-
- XtAddCallback( serverSelectorList, XmNdefaultActionCallback,
- (XtCallbackProc)serverSelectionCB, serverSelectorList ) ;
- XtAddCallback( button[0], XmNactivateCallback,
- (XtCallbackProc)serverSelectionCB, serverSelectorList ) ;
- XtAddCallback( button[1], XmNactivateCallback,
- (XtCallbackProc)serverStatsCB, serverSelectorList ) ;
- XtAddCallback( button[2], XmNactivateCallback,
- (XtCallbackProc)exitCB, NULL ) ;
- XtAddCallback( button[2], XmNactivateCallback,
- (XtCallbackProc)helpCB, helpFiles ) ;
-
- addServerToList( myHostId, 0, SERVER_ST_COURSE_SEL ) ;
- XmListSelectPos( serverSelectorList, 1, True ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Create a string for adding to the server list.
- *----------------------------------------------------------------------------*/
- static XmString
- createServerListString(
- long id,
- int nClients,
- long status
- )
- {
- XmString entry ;
- char buf[512] ;
-
- sprintf( buf, "%s - (%s, %d players)", hostNameFromId( id, 0 ),
- ( status == SERVER_ST_COURSE_SEL && nClients < MAX_PLAYERS ) ?
- "open" : "closed", nClients ) ;
-
- entry = XmStringCreateLocalized( buf ) ;
-
- return( entry ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Server selection callback.
- *----------------------------------------------------------------------------*/
- static void
- serverSelectionCB(
- Widget w,
- Widget list,
- XtPointer callData
- )
- {
- ServerHost *server = serverList ;
- char *s ;
- XmString selectedServer ;
-
- if( ( s = getListSelectedString( list ) ) == NULL )
- {
- minorError( NULL, NULL,
- "Error determining server name." ) ;
- return ;
- }
-
- selectedServer = XmStringCreateLocalized( s ) ;
- XtFree( s ) ;
-
- while( server != NULL )
- {
- if( XmStringCompare( server->name, selectedServer ) )
- {
- if( server->id == myHostId )
- {
- initLocalServer() ;
- gameServerId = server->id ;
- lookForSelf = 0 ;
- self = 0 ;
- setWorkProc( VROOM_WP_FIND_SERVER, 0 ) ;
- }
- else
- {
- outFd = connectToServer( server->id ) ;
- if( outFd != -1 )
- {
- gameServerId = server->id ;
- lookForSelf = 0 ;
- setWorkProc( VROOM_WP_RUN_CLIENT, 1 ) ;
- clientFunc = clientWaitToJoin ;
- loadedCourseId = -1 ;
- busyCursor() ;
- joinDeadLine = currentTime +
- WAIT_TO_JOIN_DELAY ;
- sendServerInfoPacket( CLIENT_INFO_JOIN,
- 0 ) ;
- }
- }
- XmStringFree( selectedServer ) ;
- return ;
- }
- server = server->next ;
- }
-
- XmStringFree( selectedServer ) ;
- minorError( NULL, NULL, "Could not find server in list!" ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Server stats callback.
- *----------------------------------------------------------------------------*/
- static void
- serverStatsCB(
- Widget w,
- Widget list,
- XtPointer callData
- )
- {
- ServerHost *server = serverList ;
- char *s ;
- XmString selectedServer ;
-
- if( ( s = getListSelectedString( list ) ) == NULL )
- {
- minorError( NULL, NULL,
- "Error determining server name." ) ;
- return ;
- }
-
- selectedServer = XmStringCreateLocalized( s ) ;
- XtFree( s ) ;
-
- while( server != NULL )
- {
- if( XmStringCompare( server->name, selectedServer ) )
- {
- postInfo( NULL, NULL, "Status for %s: %s.\n\n%d"
- " players.", hostNameFromId( server->id, 0 ),
- serverStatusString[server->status],
- server->nClients ) ;
- XmStringFree( selectedServer ) ;
- return ;
- }
- server = server->next ;
- }
-
- minorError( NULL, NULL, "Could not find server in list!" ) ;
- XmStringFree( selectedServer ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Initialize the multicast listening port and start up a work process to
- * listen for servers.
- *----------------------------------------------------------------------------*/
- void
- listenForServers(
- void
- )
- {
- int port ;
-
- port = getPort( VROOM_CLIENT_INPUT_SERVICE, VROOM_CLIENT_INPUT_PORT ) ;
-
- if( ( inFd = openMulticastSocket( &inAddr, port, 0, 0, VROOM_GROUP,
- NULL, "r" ) ) < 0 )
- {
- fatalError( "Could not open multicast socket for input." ) ;
- }
-
- /*
- * Turn on non-blocking I/O
- */
- if( fcntl( inFd, F_SETFL, FNDELAY ) < 0 ) {
- fatalError( "fcntl F_SETFL, FNDELAY:\n %s",
- strerror( errno ) ) ;
- }
-
- setWorkProc( VROOM_WP_FIND_SERVER, 1 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Work proc to listen for servers.
- *----------------------------------------------------------------------------*/
- void
- serverFind(
- void
- )
- {
- int cnt ;
- int id ;
- outputPacket packet ;
- int st = 0 ;
- int number ;
- int inAddrLen ;
- int socketEmpty = 0 ;
- static int newer = 0 ;
-
- while( !socketEmpty ) {
- cnt = recvfrom( inFd, (char *)&packet,
- sizeof( outputPacket ), 0, &inAddr,
- &inAddrLen ) ;
- if( cnt < 0 && errno == EWOULDBLOCK )
- {
- socketEmpty = 1 ;
- }
- else
- {
- switch( packet.base.type )
- {
- case SERVER_P_COURSE :
- st = processServerCoursePacket( &packet.course,
- cnt ) ;
- break ;
-
- case SERVER_P_STATUS :
- st = processServerStatusPacket( &packet.status,
- cnt ) ;
- break ;
-
- case SERVER_P_ACK :
- st = processServerAckPacket( &packet.ack, cnt );
- break ;
-
- case SERVER_P_RACE :
- if( cnt != sizeof( packet.race ) )
- {
- st = sizeof( packet.race ) ;
- }
- break ;
-
- case SERVER_P_NAME :
- st = processServerNamePacket( &packet.name,
- cnt ) ;
- break ;
-
- case SERVER_P_MESSAGE :
- st = processServerMsgPacket( &packet.msg,
- cnt ) ;
- break ;
-
- default :
- if( ( packet.base.type & 0xffffff00 ) ==
- ( SERVER_PACKET_BASE_ID & 0xffffff00 )
- && ( packet.base.type & 0xfffffff0 ) >
- SERVER_PACKET_BASE_ID && newer == 0 )
- {
- newer = 1 ;
- postInfo( NULL, NULL,
- "An newer version of %s is"
- " being played on the net.\n\n",
- basename ) ;
- }
- else
- {
- printf( "wierd packet type 0x%08x\n",
- packet.base.type ) ;
- }
- break ;
- }
- if( st )
- {
- fprintf( stderr, "received odd packet size of "
- "%d (type %d)! (id = 0x%08x)\n",
- cnt, packet.base.type, packet.base.id );
- st = 0 ;
- }
- }
- }
- checkServers() ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check if input host has been heard before.
- *----------------------------------------------------------------------------*/
- static ServerHost *
- checkForNewHost(
- outStatusPacket *bp
- )
- {
- ServerHost *server = serverList ;
-
- while( server != NULL )
- {
- if( server->id == bp->id )
- {
- return( server ) ;
- }
- else
- {
- server = server->next ;
- }
- }
-
- return( addServerToList( bp->id, bp->nPlayers, bp->status ) ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Add a server to the server list.
- *----------------------------------------------------------------------------*/
- static ServerHost *
- addServerToList(
- long id,
- int n,
- long status
- )
- {
- ServerHost *server ;
- XmString serverName ;
-
- server = (ServerHost *)myMalloc( sizeof( ServerHost ) ) ;
- server->id = id ;
- server->next = serverList ;
- server->status = status ;
- server->nClients = n ;
- server->nextDeadLine = currentTime + SERVER_TIMEOUT ;
-
- serverList = server ;
-
- nServers++ ;
-
- server->name = createServerListString( id, n, status ) ;
-
- XmListAddItem( serverSelectorList, server->name, 0 ) ;
-
- return( server ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Try to establish a connection to the server.
- *----------------------------------------------------------------------------*/
- static int
- connectToServer(
- long id
- )
- {
- int sock ;
- int port ;
- struct hostent *hp ;
- struct in_addr sin ;
-
- if( ( sock = socket( AF_INET, SOCK_DGRAM, 0 ) ) < 0 )
- {
- minorError( NULL, NULL, "socket: %s", strerror( errno ) ) ;
- return( -1 ) ;
- }
-
- /*
- * Initialize socket address to the server's address.
- */
- bzero( (char *)&outAddr, sizeof( outAddr ) ) ;
- outAddr.sin_family = AF_INET ;
-
- sin.s_addr = id ;
- if( ( hp = gethostbyaddr( &sin, sizeof( sin ), AF_INET ) ) == NULL )
- {
- minorError( NULL, NULL, "%s: %s", hostNameFromId( id, 1 ),
- hstrerror( h_errno ) ) ;
- close( sock ) ;
- return( -1 ) ;
- }
- bcopy( hp->h_addr, &(outAddr.sin_addr.s_addr), hp->h_length ) ;
-
- port = getPort( VROOM_SERVER_INPUT_SERVICE, VROOM_SERVER_INPUT_PORT ) ;
-
- outAddr.sin_port = htons( port ) ;
-
- /*
- * Connect to the server.
- */
- if( connect( sock, &outAddr, sizeof( outAddr ) ) < 0 )
- {
- close( sock ) ;
- perror( "Connect to server" ) ;
- return( -1 ) ;
- }
-
- return( sock ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Client main loop.
- *----------------------------------------------------------------------------*/
- void
- clientRun(
- void
- )
- {
- clientFunc() ;
-
- if( currentTime > deadLineToServer )
- {
- sendServerInfoPacket( CLIENT_INFO_UPDATE, 0 ) ;
- }
-
- newRacePacket = 0 ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Function to wait to join a game.
- *----------------------------------------------------------------------------*/
- static void
- clientWaitToJoin(
- void
- )
- {
- if( currentTime > joinDeadLine )
- {
- gameServerId = 0 ;
- activePlayer = 0 ;
- lookForSelf = 0 ;
- unbusyCursor() ;
- setWorkProc( VROOM_WP_RUN_CLIENT, 0 ) ;
- closeOutput() ;
- minorError( NULL, NULL, "Server failed to "
- "acknowledge connection.\nSelect "
- "another server." ) ;
- }
- }
-
-
-
-
- /*------------------------------------------------------------------------------
- * Empty function to kill time.
- *----------------------------------------------------------------------------*/
- static void
- clientNoOp(
- void
- )
- {
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Send quit signal to server and close socket.
- *----------------------------------------------------------------------------*/
- static void
- closeOutput(
- void
- )
- {
- if( outFd != -1 )
- {
- sendServerInfoPacket( CLIENT_INFO_QUIT, 0 ) ;
- close( outFd ) ;
- outFd = -1 ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Send a speed packet to the server.
- *----------------------------------------------------------------------------*/
- static void
- sendServerSpeedPacket(
- void
- )
- {
- speedPacket.playerNumber = self ;
- write( outFd, (char *)&speedPacket, sizeof( speedPacket ) ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Send an info packet to the server.
- *----------------------------------------------------------------------------*/
- static void
- sendServerInfoPacket(
- int option,
- int choice
- )
- {
- inInfoPacket packet ;
-
- packet.type = CLIENT_P_INFO ;
- packet.id = myHostId ;
- packet.option = option ;
- packet.choice = choice ;
-
- write( outFd, (char *)&packet, sizeof( packet ) ) ;
-
- deadLineToServer = currentTime + CLIENT_UPDATE_FREQ ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Inform server of my name.
- *----------------------------------------------------------------------------*/
- static void
- sendServerNamePacket(
- void
- )
- {
- inNamePacket packet ;
-
- packet.type = CLIENT_P_NAME ;
- packet.id = myHostId ;
- strncpy( packet.name, myName, sizeof( packet.name ) ) ;
-
- write( outFd, (char *)&packet, sizeof( packet ) ) ;
-
- deadLineToServer = currentTime + CLIENT_UPDATE_FREQ ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Send a text message to the server.
- *----------------------------------------------------------------------------*/
- void
- sendServerMsgPacket(
- char *msg
- )
- {
- inMsgPacket packet ;
-
- if( gameServerId != myHostId )
- {
- packet.type = CLIENT_P_MESSAGE ;
- packet.id = myHostId ;
- strncpy( packet.msg, msg, sizeof( packet.msg ) ) ;
- packet.msg[sizeof( packet.msg ) - 1] = '\0' ;
-
- write( outFd, (char *)&packet, sizeof( packet ) ) ;
-
- deadLineToServer = currentTime + CLIENT_UPDATE_FREQ ;
- }
- else
- {
- broadcastMsgPacket( self, msg ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Process a status packet from a server (in find server mode).
- *----------------------------------------------------------------------------*/
- static int
- processServerStatusPacket(
- outStatusPacket *packet,
- int size
- )
- {
- int i ;
- int *selList ;
- int selCnt ;
- ServerHost *server ;
- XmString oldListEntry ;
-
- if( size != sizeof( outStatusPacket ) )
- {
- return( -1 ) ;
- }
-
- server = checkForNewHost( packet ) ;
-
- if( server->nClients != packet->nPlayers ||
- server->status != packet->status )
- {
- if( server->id == gameServerId &&
- packet->nPlayers != server->nClients )
- {
- updateServerCourseLabel( packet->nPlayers ) ;
- }
-
- oldListEntry = server->name ;
- server->nClients = packet->nPlayers ;
- server->status = packet->status ;
- server->name = createServerListString( server->id,
- server->nClients, server->status ) ;
- XmListReplaceItems( serverSelectorList, &oldListEntry, 1,
- &(server->name) ) ;
- if( !XmListGetSelectedPos( serverSelectorList, &selList,
- &selCnt ) )
- {
- XmListSelectItem( serverSelectorList, server->name,
- True ) ;
- }
- else
- {
- XtFree( (char *)selList ) ;
- }
- XmStringFree( oldListEntry ) ;
- }
-
- server->nextDeadLine = currentTime + SERVER_TIMEOUT ;
-
- if( server->id == gameServerId )
- {
- if( lookForSelf == 1 || checkIds == 1 )
- {
- findSelf( server->id, packet->playerId ) ;
- }
- serverStatus = packet->status ;
- }
-
-
- if( packet->status == SERVER_ST_QUIT )
- {
- if( packet->id == gameServerId )
- {
- resetToServerSearch() ;
- minorError( startTeamModeCB, NULL,
- "Game server (%s) quit.\n"
- "Game aborted. Choose another server.",
- hostNameFromId( server->id, 0 ) );
- }
- removeServer( packet->id ) ;
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Process an acknowledgement package from the server.
- *----------------------------------------------------------------------------*/
- static int
- processServerAckPacket(
- outAckPacket *packet,
- int size
- )
- {
- ServerHost *server ;
-
- if( size != sizeof( outAckPacket ) )
- {
- return( 1 ) ;
- }
-
- if( ( server = findServer( packet->id ) ) != NULL )
- {
- server->nextDeadLine = currentTime + SERVER_TIMEOUT ;
- }
-
- if( packet->id == gameServerId && ( packet->targetId == myHostId ||
- packet->targetId == VROOM_ALL_PLAYERS ) )
- {
- switch( packet->status )
- {
- case ACK_ST_CANDIDATE :
- activePlayer = 1 ;
- busyCursor() ;
- sendServerInfoPacket( CLIENT_INFO_ACCEPT, 0 ) ;
- sendServerNamePacket() ;
- clientFunc = clientNoOp ;
- joinServerTime = currentTime ;
- setWorkProc( VROOM_WP_READ_SERVER, 1 ) ;
- setWorkProc( VROOM_WP_FIND_SERVER, 0 ) ;
-
- serverCourseSelector =
- createServerCourseSelector(
- serverCourseForm ) ;
- if( server )
- {
- updateServerCourseLabel(
- server->nClients ) ;
- }
- createMessageArea() ;
- setAdminForm( serverCourseForm ) ;
- unbusyCursor() ;
- lookForSelf = 1 ;
- break ;
-
- case ACK_ST_WAIT :
- /*
- * Should put us into spectator mode until
- * such a time as the server can let us join.
- * Will have to add this later.
- */
- resetToServerSearch() ;
- minorError( startTeamModeCB, NULL,
- "%s is not accepting new\nplayers now."
- " Try again later or try a\ndifferent "
- "server.",
- hostNameFromId( packet->id, 0 ) ) ;
- break ;
-
- case ACK_ST_DROP :
- /*
- * Dropped by server, probably due to poor
- * network connection.
- */
- resetToServerSearch() ;
- minorError( startTeamModeCB, NULL,
- "%s has dropped you.\n"
- "Try again later or try a\ndifferent "
- "server.",
- hostNameFromId( packet->id, 0 ) ) ;
- break ;
-
- case ACK_ST_COURSE_VOTE :
- if( packet->data == -1 )
- {
- minorError( NULL, NULL, "The server "
- "does not recognize your course"
- "\nselection. Choose another"
- "course." ) ;
- }
- else
- {
- busyCursor() ;
- setAdminForm( courseVoteForm ) ;
- unbusyCursor() ;
- }
- break ;
-
- case ACK_ST_COURSE_CHOSEN :
- if( packet->data != loadedCourseId )
- {
- clientLoadCourse( packet->data ) ;
- }
- break ;
- }
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Process a name package from the server.
- *----------------------------------------------------------------------------*/
- static int
- processServerNamePacket(
- outNamePacket *packet,
- int size
- )
- {
- int i ;
- ServerHost *server ;
-
- if( size != sizeof( outNamePacket ) )
- {
- return( 1 ) ;
- }
-
- if( ( server = findServer( packet->id ) ) != NULL )
- {
- server->nextDeadLine = currentTime + SERVER_TIMEOUT ;
- }
-
- if( packet->id == gameServerId )
- {
- strncpy( cars[packet->nPlayer].name, packet->name,
- sizeof( cars[packet->nPlayer].name ) ) ;
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Process a message package from the server.
- *----------------------------------------------------------------------------*/
- static int
- processServerMsgPacket(
- outMsgPacket *packet,
- int size
- )
- {
- int i ;
- ServerHost *server ;
-
- if( size != sizeof( outMsgPacket ) )
- {
- return( 1 ) ;
- }
-
- if( ( server = findServer( packet->id ) ) != NULL )
- {
- server->nextDeadLine = currentTime + SERVER_TIMEOUT ;
- }
-
- if( packet->id == gameServerId )
- {
- postNewMessage( packet->nPlayer, packet->msg ) ;
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Process a race course packet from a server (in game mode).
- *----------------------------------------------------------------------------*/
- static int
- processServerCoursePacket(
- outCoursePacket *packet,
- int size
- )
- {
- ServerHost *server ;
-
- if( size != sizeof( outCoursePacket ) )
- {
- return( -1 ) ;
- }
-
- if( packet->id == gameServerId && activePlayer )
- {
- if( addToCourseList( packet ) )
- {
- addCourseToSelectionList( serverCourseSelector,
- packet->name ) ;
- }
- }
-
- if( ( server = findServer( packet->id ) ) != NULL )
- {
- server->nextDeadLine = currentTime + SERVER_TIMEOUT ;
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Process a race packet from a server (in game mode).
- *----------------------------------------------------------------------------*/
- static int
- processServerRacePacket(
- outRacePacket *packet,
- int size
- )
- {
- int i ;
- int n ;
- int l ;
- long statusChanges ;
- float lapTime ;
- float ds ;
- ServerHost *server ;
-
- if( size != sizeof( outRacePacket ) )
- {
- return( -1 ) ;
- }
-
- if( packet->id == gameServerId )
- {
- newRacePacket = 1 ;
- bcopy( packet, &racePacket, sizeof( outRacePacket ) ) ;
- statusChanges = cars[self].status ^ racePacket.status[self] ;
- if( ( statusChanges & CAR_WIPE_OUT ) != 0 )
- {
- if( racePacket.status[self] & CAR_WIPE_OUT )
- {
- showReason( racePacket.status[self] &
- WIPE_OUT_REASON ) ;
- sfxPlay( crashSfx ) ;
- sfxSilenceLoop( squealSfx ) ;
- sfxDisable( motorSfx ) ;
- }
- else if( cars[self].status & CAR_WIPE_OUT )
- {
- setMessage( "Car set back on track." ) ;
- sfxPlay( changeLaneSfx ) ;
- sfxEnable( motorSfx ) ;
- sfxPlayPitch( motorSfx, cars[self].desiredSpeed
- * speedFactor ) ;
- }
- }
- if( ( statusChanges & CAR_SKID ) != 0 )
- {
- if( racePacket.status[self] & CAR_SKID )
- {
- sfxPlay( squealSfx ) ;
- }
- else
- {
- sfxSilenceLoop( squealSfx ) ;
- }
- }
- if( ( racePacket.status[self] & CAR_BUMP ) != 0 )
- {
- sfxPlay( collideSfx ) ;
- }
- ds = cars[self].desiredSpeed ;
- for( i = 0 ; i < MAX_PLAYERS ; i++ )
- {
- cars[i].status = racePacket.status[i] ;
- player[i].x = racePacket.x[i] ;
- player[i].y = racePacket.y[i] ;
- player[i].z = racePacket.z[i] ;
- player[i].thetaDeg = racePacket.thetaDeg[i] ;
- player[i].roll = racePacket.roll[i] ;
- player[i].headingDeg = racePacket.headingDeg[i] ;
- cars[i].totalDis = racePacket.totalDis[i] ;
- cars[i].desiredSpeed = racePacket.desiredSpeed[i] ;
- cars[i].lane = racePacket.lane[i] ;
- player[i].place = racePacket.position[i] ;
- teamPosition[player[i].place-1] = i ;
- }
- cars[self].desiredSpeed = ds ;
-
- if( packet->mode == SERVER_ST_PRE_RACE ||
- packet->mode == SERVER_ST_POST_TRIAL )
- {
- for( i = 0 ; i < MAX_PLAYERS ; i++ )
- {
- cars[i].bestLapTime = racePacket.indTime[i] ;
- }
- }
-
- if( ( cars[self].status & ( CHANGE_LANES ) ) == steering )
- {
- if( steering )
- {
- sfxPlay( changeLaneSfx ) ;
- }
- steering = 0 ;
- }
- if( ( cars[self].status & CAR_WIPE_OUT ) != 0 )
- {
- steering = 0 ;
- }
-
- i = ( (int)racePacket.totalDis[self] ) + 1 ;
- /*
- * Check to see to compute new best time trial lap time.
- */
- n = ( i - 1 ) / nTracks ;
- i = i % nTracks ;
- if( ( packet->mode == SERVER_ST_TRIAL ||
- packet->mode == SERVER_ST_POST_TRIAL ) && i == 1 &&
- cars[self].track->number == 0 )
- {
- lapTime = racePacket.time - racePacket.indTime[self] ;
- if( n == 1 || lapTime - cars[self].startLapTime <
- cars[self].bestLapTime )
- {
- cars[self].bestLapTime = lapTime -
- cars[self].startLapTime ;
- setMessage( "Best lap (unofficial): %s",
- raceTimeString( cars[self].bestLapTime,
- &l ) ) ;
- }
- cars[self].startLapTime = lapTime ;
- }
- cars[self].lap = n ;
- n = nTracks ;
- while( cars[self].track->number != i )
- {
- cars[self].track = cars[self].track->nextTrack ;
- if( --n < 0 )
- {
- fatalError( "Bad track number computed from"
- "server information. Aborting." ) ;
- }
- }
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Read input from the game server.
- *----------------------------------------------------------------------------*/
- void
- serverRead(
- void
- )
- {
- int cnt ;
- int id ;
- outputPacket packet ;
- int st = 0 ;
- int number ;
- int inAddrLen ;
- int socketEmpty = 0 ;
- static int newer = 0 ;
-
- while( !socketEmpty ) {
- cnt = recvfrom( inFd, (char *)&packet,
- sizeof( outputPacket ), 0, &inAddr,
- &inAddrLen ) ;
- if( cnt < 0 && errno == EWOULDBLOCK )
- {
- socketEmpty = 1 ;
- }
- else
- {
- switch( packet.base.type )
- {
- case SERVER_P_COURSE :
- st = processServerCoursePacket( &packet.course,
- cnt ) ;
- break ;
-
- case SERVER_P_STATUS :
- st = processServerStatusPacket( &packet.status,
- cnt ) ;
- break ;
-
- case SERVER_P_ACK :
- st = processServerAckPacket( &packet.ack, cnt );
- break ;
-
- case SERVER_P_RACE :
- st = processServerRacePacket( &packet.race,
- cnt ) ;
- break ;
-
- case SERVER_P_NAME :
- st = processServerNamePacket( &packet.name,
- cnt ) ;
- break ;
-
- case SERVER_P_MESSAGE :
- st = processServerMsgPacket( &packet.msg,
- cnt ) ;
- break ;
-
- default :
- if( ( packet.base.type & 0xffffff00 ) ==
- ( SERVER_PACKET_BASE_ID & 0xffffff00 )
- && ( packet.base.type & 0xfffffff0 ) >
- SERVER_PACKET_BASE_ID && newer == 0 )
- {
- newer = 1 ;
- postInfo( NULL, NULL,
- "An newer version of %s is"
- " being played on the net.\n\n",
- basename ) ;
- }
- else
- {
- printf( "wierd packet type 0x%08x\n",
- packet.base.type ) ;
- }
- break ;
- }
- if( st )
- {
- fprintf( stderr, "received odd packet size of "
- "%d (type 0x%08x)! (id = 0x%08x)\n",
- cnt, packet.base.type, packet.base.id );
- st = 0 ;
- }
- }
- }
-
- checkServers() ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Exit the game from client mode.
- *----------------------------------------------------------------------------*/
- void
- exitClientCB(
- Widget w,
- XtPointer clientData,
- XtPointer callData
- )
- {
- closeOutput() ;
- exitCB( w, clientData, callData ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Locate a host in the server list.
- *----------------------------------------------------------------------------*/
- static ServerHost *
- findServer(
- long id
- )
- {
- ServerHost *server = serverList ;
-
- while( server != NULL && server->id != id )
- {
- server = server->next ;
- }
-
- return( server ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check for server timeouts.
- *----------------------------------------------------------------------------*/
- static void
- checkServers(
- void
- )
- {
- ServerHost *server = serverList ;
- ServerHost *prev ;
-
- if( currentTime > nextDeadLine )
- {
- if( serverList != NULL )
- {
- nextDeadLine = serverList->nextDeadLine ;
- }
- while( server != NULL )
- {
- if( server->id != myHostId &&
- server->nextDeadLine < currentTime )
- {
- prev = server ;
- server = server->next ;
- removeServer( prev->id ) ;
- }
- else
- {
- nextDeadLine = MINFUNC( server->nextDeadLine,
- nextDeadLine ) ;
- server = server->next ;
- }
- }
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Remove a server from the server list.
- *----------------------------------------------------------------------------*/
- static void
- removeServer(
- long id
- )
- {
- int *selList ;
- int selCnt ;
- Widget form ;
- ServerHost *server = serverList ;
- ServerHost *prev = NULL ;
- XmString serverName ;
-
- while( server != NULL && server->id != id )
- {
- prev = server ;
- server = server->next ;
- }
-
- if( server->id == id )
- {
- if( prev == NULL )
- {
- serverList = server->next ;
- }
- else
- {
- prev->next = server->next ;
- }
- server->name = createServerListString( id, server->nClients,
- server->status ) ;
- XmListDeleteItem( serverSelectorList, server->name ) ;
- XmStringFree( server->name ) ;
- if( !XmListGetSelectedPos( serverSelectorList, &selList,
- &selCnt ) )
- {
- XmListSelectPos( serverSelectorList, 1, True ) ;
- }
- else
- {
- XtFree( (char *)selList ) ;
- }
- free( server ) ;
- nServers-- ;
-
- if( id == gameServerId )
- {
- minorError( startTeamModeCB, NULL,
- "Game server (%s) stopped\n"
- "transmitting or responded too slowly.\n"
- "Game aborted. Choose another server.",
- hostNameFromId( id, 0 ) );
- resetToServerSearch() ;
- }
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Callback for selecting a server course.
- *----------------------------------------------------------------------------*/
- void
- serverCourseSelectionCB(
- Widget w,
- Widget list,
- XtPointer callData
- )
- {
- char *courseName ;
- outCoursePacket *course ;
-
- if( ( courseName = getListSelectedString( list ) ) == NULL )
- {
- minorError( NULL, NULL,
- "Error determining course file name." ) ;
- }
- else
- {
- course = findCourseInList( courseName ) ;
-
- if( course == NULL )
- {
- minorError( NULL, NULL, "Could not find selected "
- "course `%s' in list.", courseName ) ;
- }
- else
- {
- if( gameServerId == myHostId )
- {
- clientChoseCourse( myHostId,
- course->courseId ) ;
- }
- else
- {
- sendServerInfoPacket( CLIENT_INFO_COURSE_SEL,
- course->courseId ) ;
- }
- }
- XtFree( courseName ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Course selected -- load it and prepare for time trials.
- *----------------------------------------------------------------------------*/
- static void
- clientLoadCourse(
- long courseId
- )
- {
- int st ;
-
- if( ( st = loadTrackFromId( courseId ) ) == 0 )
- {
- sendServerInfoPacket( CLIENT_INFO_COURSE_ACK, courseId ) ;
- loadedCourseId = courseId ;
- cars[self].track = getTrack( 0 ) ;
- startTimeTrials( 0 ) ;
- }
- else if( st == -1 )
- {
- sendServerInfoPacket( CLIENT_INFO_COURSE_REQ, courseId ) ;
- }
- else
- {
- sendServerInfoPacket( CLIENT_INFO_QUIT, 0 ) ;
- fatalError( "Error creating race course. Aborting." ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Initialize for networked game.
- *----------------------------------------------------------------------------*/
- void
- initTeamGame(
- void
- )
- {
- sfxEnable( motorSfx ) ;
- sfxPlayPitch( motorSfx, 0.0f ) ;
- if( gameServerId != myHostId )
- {
- clientFunc = clientPreTrial ;
- startSoundTime = 2.0f ;
- checkIds = 1 ;
- initSoloCars( 1 ) ;
- nCars = 1 ;
- steering = 0 ;
- speedPacket.type = CLIENT_P_SPEED ;
- speedPacket.id = myHostId ;
- speedPacket.speed = 0.0f ;
- }
-
- setMessage( "Prepare to qualify." ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Pre-trial loop.
- *----------------------------------------------------------------------------*/
- static void
- clientPreTrial(
- void
- )
- {
- if( newRacePacket )
- {
- sfxPlayPitch( motorSfx, 0.5f * cars[self].desiredSpeed *
- speedFactor ) ;
- if( racePacket.mode == SERVER_ST_TRIAL )
- {
- sfxPlay( startSfx ) ;
- sfxPlayPitch( motorSfx, cars[self].desiredSpeed *
- speedFactor ) ;
- clientFunc = clientTrial ;
- cars[self].startLapTime = racePacket.time -
- racePacket.indTime[self];
- setMessage( "Best of %d laps is used to qualify.",
- VROOM_TRIAL_LAPS ) ;
- }
- else if( racePacket.time < startSoundTime )
- {
- sfxPlay( toneSfx ) ;
- startSoundTime -= 1.0f ;
- }
- drawIt( self ) ;
- drawPreTrialOverlay( racePacket.time, teamPosition, 1, 0 ) ;
- GLwDrawingAreaSwapBuffers( mainOgl ) ;
- }
- }
-
-
- /*------------------------------------------------------------------------------
- * Trial loop.
- *----------------------------------------------------------------------------*/
- static void
- clientTrial(
- void
- )
- {
- int l ;
-
- if( newRacePacket )
- {
- updateSpeed() ;
- drawIt( self ) ;
- drawTrialOverlay( racePacket.indTime[self], teamPosition ) ;
- GLwDrawingAreaSwapBuffers( mainOgl ) ;
-
- if( ( cars[self].status & CAR_FINISHED ) != 0 ||
- ( racePacket.mode != SERVER_ST_TRIAL &&
- racePacket.mode != SERVER_ST_POST_TRIAL ) )
- {
- clientFunc = clientPostTrial ;
- setMessage( "Waiting for all players to qualify.\n" ) ;
- sfxDisable( motorSfx ) ;
- sfxSilenceLoop( squealSfx ) ;
- }
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Loop for after time trials.
- *----------------------------------------------------------------------------*/
- static void
- clientPostTrial(
- void
- )
- {
- int i ;
-
- if( newRacePacket )
- {
- if( racePacket.mode != SERVER_ST_POST_TRIAL &&
- racePacket.mode != SERVER_ST_TRIAL )
- {
- clientFunc = clientPreRace ;
- i = teamPosition[0] ;
- showRecord = checkLapRecord( racePacket.indTime[i],
- cars[i].name, 0 ) ;
- sfxEnable( motorSfx ) ;
- startSoundTime = 2.0f ;
- nCars = MAX_PLAYERS ;
- informPosition( player[self].place - 1 ) ;
- }
- drawIt( self ) ;
- drawPostTrialOverlay( racePacket.indTime[self], teamPosition ) ;
- GLwDrawingAreaSwapBuffers( mainOgl ) ;
-
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Loop for pre-race.
- *----------------------------------------------------------------------------*/
- static void
- clientPreRace(
- void
- )
- {
- float dTime ;
-
- if( newRacePacket )
- {
- dTime = racePacket.time ;
- sfxPlayPitch( motorSfx, 0.5f * cars[self].desiredSpeed *
- speedFactor ) ;
- if( dTime <= 0.0f || racePacket.mode != SERVER_ST_PRE_RACE )
- {
- sfxPlay( startSfx ) ;
- sfxPlayPitch( motorSfx, cars[self].desiredSpeed *
- speedFactor ) ;
- clientFunc = clientRace ;
- startLastLap = 0 ;
- setMessage( "May the best driver win." ) ;
- dTime = 0.0f ;
- }
- else if( racePacket.time < startSoundTime )
- {
- sfxPlay( toneSfx ) ;
- startSoundTime -= 1.0f ;
- }
- drawIt( 0 ) ;
- drawPreTrialOverlay( racePacket.time, teamPosition, 0,
- showRecord ) ;
- GLwDrawingAreaSwapBuffers( mainOgl ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Loop for race.
- *----------------------------------------------------------------------------*/
- static void
- clientRace(
- void
- )
- {
- int n ;
- int dLaps ;
-
- if( newRacePacket )
- {
- updateSpeed() ;
- if( ( cars[self].status & CAR_FINISHED ) != 0 )
- {
- clientFunc = clientPostRace ;
- sfxDisable( motorSfx ) ;
- sfxSilenceLoop( squealSfx ) ;
- showFinishMessage() ;
- drawIt( 0 ) ;
- }
- else
- {
- if( cars[self].lap == raceLaps - 1 &&
- startLastLap == 0 )
- {
- startLastLap = 1 ;
- sfxPlay( lastlapSfx ) ;
- }
- drawIt( 0 ) ;
- if( player[self].place == 1 )
- {
- dLaps = (int)( cars[self].totalDis -
- cars[teamPosition[1]].totalDis ) /
- nTracks ;
- drawRaceOverlay( racePacket.time,
- raceLaps - cars[self].lap - 1, dLaps, 1,
- teamPosition ) ;
- }
- else
- {
- n = teamPosition[0] ;
- if( cars[n].status & CAR_FINISHED )
- {
- dLaps = raceLaps - cars[self].lap - 1 ;
- }
- else
- {
- dLaps = (int)( cars[n].totalDis -
- cars[self].totalDis ) /
- nTracks ;
- }
- drawRaceOverlay( racePacket.time,
- raceLaps - cars[self].lap - 1, dLaps, 0,
- teamPosition ) ;
- }
- }
- GLwDrawingAreaSwapBuffers( mainOgl ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Loop for post race.
- *----------------------------------------------------------------------------*/
- static void
- clientPostRace(
- void
- )
- {
- int i ;
-
- if( newRacePacket )
- {
- drawIt( 0 ) ;
- drawPostRaceOverlay( racePacket.indTime[self], racePacket.time,
- teamPosition ) ;
- GLwDrawingAreaSwapBuffers( mainOgl ) ;
- }
-
- if( serverStatus == SERVER_ST_RESULTS )
- {
- clientFunc = clientNoOp ;
- for( i = 0 ; i < MAX_PLAYERS ; i++ )
- {
- cars[i].finishTime = racePacket.indTime[i] ;
- }
- showTeamResults( teamPosition ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Clean up from team mode when exitting.
- *----------------------------------------------------------------------------*/
- void
- teamExit(
- void
- )
- {
- if( gameServerId != myHostId )
- {
- closeOutput() ;
- }
- else
- {
- closeServer() ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Reset everything to begin server search again.
- *----------------------------------------------------------------------------*/
- static void
- resetToServerSearch(
- void
- )
- {
- busyCursor() ;
- gameServerId = 0 ;
- activePlayer = 0 ;
- checkIds = 0 ;
- lookForSelf = 0 ;
- closeOutput() ;
- clearCourseList() ;
- sfxDisable( motorSfx ) ;
- sfxSilenceLoop( squealSfx ) ;
- setWorkProc( VROOM_WP_FIND_SERVER, 1 ) ;
- setWorkProc( VROOM_WP_RUN_CLIENT, 0 ) ;
- setWorkProc( VROOM_WP_READ_SERVER, 0 ) ;
- unbusyCursor() ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Find self in server's playerId list.
- *----------------------------------------------------------------------------*/
- static void
- findSelf(
- long serverId,
- long playerId[]
- )
- {
- int i ;
-
- self = -1 ;
- for( i = 0 ; i < MAX_PLAYERS ; i++ )
- {
- if( playerId[i] == myHostId )
- {
- self = i ;
- lookForSelf = 0 ;
- return ;
- }
- }
-
- if( self == -1 && currentTime > joinServerTime + 5.0f )
- {
- resetToServerSearch() ;
- minorError( startTeamModeCB, NULL,
- "Game server (%s) no longer\n"
- "recognizes you. Game aborted. "
- "Choose another server.",
- hostNameFromId( serverId, 0 ) );
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Reset for starting next team game.
- *----------------------------------------------------------------------------*/
- void
- restartTeamCB(
- Widget w,
- XtPointer clientData,
- XtPointer callData
- )
- {
- busyCursor() ;
-
- setAdminForm( serverCourseForm ) ;
-
- if( gameServerId != myHostId )
- {
- clientFunc = clientNoOp ;
- loadedCourseId = -1 ;
- lookForSelf = 1 ;
- nCars = 1 ;
- }
- else
- {
- setServerForNextGame() ;
- }
-
- unbusyCursor() ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Loop for spectating.
- *----------------------------------------------------------------------------*/
- static void
- clientSpectate(
- void
- )
- {
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check if need to send server new speed.
- *----------------------------------------------------------------------------*/
- static void
- updateSpeed(
- void
- )
- {
- if( speedPacket.speed != cars[self].desiredSpeed ||
- ( speedPacket.steer != steering ) )
- {
- sfxPlayPitch( motorSfx, cars[self].desiredSpeed * speedFactor );
- speedPacket.speed = cars[self].desiredSpeed ;
- speedPacket.steer = steering ;
- sendServerSpeedPacket() ;
- }
- }
-