home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 1 / CD_Magazyn_EXEC_nr_1.iso / Gry / battalion.lha / Battalion / source / net.c < prev    next >
C/C++ Source or Header  |  1999-12-23  |  33KB  |  1,054 lines

  1. /****************************************************************/
  2. /* code copyright 1995-1996 Andrew Johnson - ALL RIGHTS RESERVED*/
  3. /*                          ajohnson@eecs.uic.edu               */
  4. /*                                                              */
  5. /*                      Electronic Visualization Lab (M/C 154)  */
  6. /*                      University of Illinois at Chicago       */
  7. /*                      851 South Morgan St. Room 1120 SEO      */
  8. /*                      Chicago, IL 60607-7053                  */
  9. /*                                                              */
  10. /*                      (312) 996-3002     (312) 413-7585 FAX   */
  11. /***********************************************************************/
  12. /* net.c  v 1.3                                                        */
  13. /* network routines for battalion                                      */
  14. /***********************************************************************/
  15.  
  16. /* the network coding is pretty much alpha-stage stuff. It seems
  17.  * to generally work though the monster positions are slightly off
  18.  * in the remote versions making it hard to hit the other person.
  19.  * 
  20.  * the vapour also has a problem getting kills on the other monsters
  21.  * 
  22.  * ocassionally wehn switching from demo to game mode the screen goes
  23.  * black and everything stops
  24.  */
  25. #include "battalion.h"
  26.  
  27. /*****************/
  28. /* network stuff */
  29. /*****************/
  30.  
  31. #ifdef AMIGAVERSION
  32. struct Library *SocketBase = NULL;  /* bsdsocket.library */
  33. #define SOCKETVERSION 4             /* required version */
  34. static long ioctl_true = 1;
  35. #endif
  36.  
  37. struct sockaddr_in serv_addr;
  38. struct sockaddr_in clients[MAXCLIENTS];
  39. struct sockaddr_in cli_addr;
  40.  
  41. long clientsFrom[MAXCLIENTS];
  42. int lastClientMonsterUpdate[MAXCLIENTS];
  43.  
  44. time_t clientsAlive[MAXCLIENTS];
  45. time_t lastRecvTime;
  46. time_t lastNotDeadYetTime;
  47. int lastMonsterUpdate;
  48.  
  49. int numClients;
  50. int sockfd;
  51. int portNumber;
  52. int connected;
  53.  
  54. int waitCounter     = 0;
  55. int beamOnSinceLast = 0;
  56. int tankModulator   = 0;
  57.  
  58. char hostAddr[40];
  59.  
  60. extern float globalxshift;
  61. extern float globalzshift;
  62.  
  63. extern struct targetInfo * targets;
  64.  
  65.  
  66. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  67.  
  68. void turnBeamOnSinceLast()
  69.     {
  70.     beamOnSinceLast = 1;
  71.     }
  72.     
  73. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  74.  
  75. void setUnconnected()
  76.     {
  77.     connected = 0;
  78.     }
  79.     
  80. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  81.  
  82. void setPortNumber(int val)
  83.     {
  84.     portNumber = val;
  85.     }
  86.     
  87. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  88.  
  89. void setHostAddr(char * val)
  90.     {
  91.     strcpy(hostAddr, val);
  92.     }
  93. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  94.  
  95. int HostnameToIP(char *hostname, char *hostIP)
  96.     {
  97.     struct hostent* host;
  98.  
  99.     host = gethostbyname(hostname);
  100.  
  101.     if (host)
  102.         {
  103.         sprintf(hostIP,"%d.%d.%d.%d",
  104.                 (int)((unsigned char)host->h_addr_list[0][0]),
  105.                 (int)((unsigned char)host->h_addr_list[0][1]),
  106.                 (int)((unsigned char)host->h_addr_list[0][2]),
  107.                 (int)((unsigned char)host->h_addr_list[0][3]));
  108.         }
  109.     else
  110.         return(0);
  111.  
  112.     return (1);
  113.     }
  114.  
  115. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  116. #ifdef AMIGAVERSION
  117.  
  118. void amiga_netexit()
  119. {
  120.   CloseLibrary(SocketBase);
  121. }
  122.  
  123. int amiga_netinit()
  124. {
  125.   if (!(SocketBase = OpenLibrary("bsdsocket.library",SOCKETVERSION))) {
  126.     printf("Can't open bsdsocket.library V%d!\n",SOCKETVERSION);
  127.     return (0);
  128.   }
  129.   if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),&errno,
  130.                          SBTM_SETVAL(SBTC_LOGTAGPTR),"Battalion",
  131.                          TAG_END)) {
  132.     printf("Can't set errno-pointer!\n");
  133.     CloseLibrary(SocketBase);
  134.     return(0);
  135.   }
  136.   atexit(amiga_netexit);
  137.   return (-1);
  138. }
  139.  
  140. #endif
  141. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  142.  
  143. int setUpClient()
  144.     {
  145.     char hostIP[40];
  146.  
  147.     lastMonsterUpdate = -1;
  148.     lastRecvTime = lastNotDeadYetTime = 0;
  149. #ifdef AMIGAVERSION
  150.     if (!amiga_netinit())
  151.       return (0);
  152. #endif
  153.  
  154.     /************************/
  155.     /* Open datagram socket */
  156.     /************************/
  157.     
  158.     if ((sockfd = socket(AF_INET, SOCK_DGRAM,0)) < 0)
  159.         {
  160.         printf("battalion client cannot open datagram socket\n");
  161.         return(0);
  162.         }
  163.  
  164.     /*****************************/
  165.     /* Prepare client to connect */
  166.     /*****************************/
  167.     
  168.     bzero((char *) &cli_addr, sizeof(cli_addr));
  169.     cli_addr.sin_family = AF_INET;
  170.     cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  171.     cli_addr.sin_port = htons(0);
  172.  
  173.     if (bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
  174.         {
  175.         printf("battalion client cannot bind local address\n");
  176.         return(0);
  177.         }
  178.  
  179.     /****************************************************************/
  180.     /* Set up data structure to indicate which server to connect to */
  181.     /****************************************************************/
  182.     
  183.     if ((hostAddr[0] >= '0') && (hostAddr[0] <= '9'))
  184.         {
  185.         strcpy (hostIP, hostAddr);
  186.         }
  187.     else
  188.         {
  189.         if(!HostnameToIP(hostAddr, hostIP))
  190.             {
  191.             strcpy (hostIP, hostAddr);
  192.             }
  193.         }
  194.         
  195.     bzero((char *) &serv_addr, sizeof(serv_addr));
  196.     serv_addr.sin_family = AF_INET;
  197.     serv_addr.sin_addr.s_addr = inet_addr(hostIP);
  198.     serv_addr.sin_port = htons(portNumber);
  199.  
  200.     printf("battalion client running - looking for server on %s (%s) on port %d\n\n", hostAddr, hostIP, portNumber);
  201.  
  202.     /*******************/
  203.     /* set nonblocking */
  204.     /*******************/
  205.     
  206. #ifndef AMIGAVERSION
  207.     fcntl(sockfd,F_SETFL,FNDELAY);
  208. #else
  209.     IoctlSocket(sockfd,FIONBIO,(char *)&ioctl_true);
  210. #endif
  211.  
  212.     return(1);
  213.     }
  214.  
  215.  
  216. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  217.  
  218. int setUpNetwork()
  219.     {
  220.     int i;
  221.     char host[MAXHOSTNAMELEN];
  222.     char hostIP[MAXHOSTNAMELEN];
  223.  
  224. #ifdef AMIGAVERSION
  225.     if (!amiga_netinit())
  226.       return (0);
  227. #endif
  228.  
  229.     /************************/
  230.     /* Open datagram socket */
  231.     /************************/
  232.     
  233.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  234.         {
  235.         printf("Server cannot open datagram socket\n");
  236.         return(0);
  237.         }
  238.  
  239.     /******************************************************/
  240.     /* Set up server to allow connection from any address */
  241.     /******************************************************/
  242.     
  243.     bzero((char *) &serv_addr, sizeof(serv_addr));
  244.     serv_addr.sin_family = AF_INET;
  245.     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  246.     
  247.     
  248.     serv_addr.sin_port = htons(portNumber);
  249.  
  250.     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
  251.         {
  252.         printf("battalion server cannot bind to local address\n");
  253.         return(0);
  254.         }
  255.  
  256.     gethostname(host,MAXHOSTNAMELEN);
  257.     HostnameToIP(host, hostIP);
  258.  
  259.     printf("battalion server running on %s (%s) on port %d\n\n", host, hostIP, portNumber);
  260.  
  261.     /*******************/
  262.     /* set nonblocking */
  263.     /*******************/
  264.     
  265. #ifndef AMIGAVERSION
  266.     fcntl(sockfd,F_SETFL,FNDELAY);
  267. #else
  268.     IoctlSocket(sockfd,FIONBIO,(char *)&ioctl_true);
  269. #endif
  270.  
  271.     /******************/
  272.     /* no clients yet */
  273.     /******************/
  274.     
  275.     numClients = 0;
  276.  
  277.     for (i=0; i<MAXCLIENTS;i++)
  278.         {
  279.         clientsAlive[i] = 0;
  280.         lastClientMonsterUpdate[i] = -1;
  281.         }
  282.  
  283.     return(1);
  284.     }
  285.    
  286.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  287.  
  288. void updateNetworkBuildings(char * recvline, struct tree * treelist)
  289.     {
  290.     char command[MAXLINE];
  291.     char mesg[MAXLINE];
  292.     int buildingNumber;
  293.     int i;
  294.     struct tree * temptree;
  295.    
  296.     /*****************************************************/
  297.     /* find out which building was destroyed by a client */
  298.     /*****************************************************/
  299.     
  300.     sscanf(recvline, "%s %d", command, &buildingNumber);
  301.  
  302.     for (temptree = treelist->next; temptree != NULL; temptree = temptree->next)
  303.         if (temptree->number == buildingNumber)
  304.             temptree->intact = 0;
  305.  
  306.     /***********************************************************************/
  307.     /* tell all the clients about the building destroyed by another client */
  308.     /***********************************************************************/
  309.     
  310.     sprintf(mesg, "%s %d #", MESG_BUILDING, buildingNumber);
  311.  
  312.     for(i=0; i<numClients; i++)
  313.         sendMessage(mesg, &clients[i], sizeof(clients[i]));
  314.     
  315.     }
  316.  
  317.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  318.  
  319. void addNewNetworkTank(char * recvline, struct tank * tanklist, 
  320.     void * arena, int sizeTank)
  321.     {
  322.     char command[MAXLINE];
  323.     float x, z;
  324.     int type, number;
  325.     float finRange, speed;
  326.     struct tank * temptank;
  327.     int foundIt;
  328.     
  329.     sscanf(recvline, "%s %d %f %f %f %f %d",
  330.         command, &number, &x, &z, &finRange, &speed, &type);
  331.  
  332.  
  333.        foundIt = 0;
  334.     for (temptank = tanklist->next; temptank != NULL; temptank = temptank->next)
  335.         {
  336.         if (number == temptank->number)
  337.             foundIt = 1;
  338.         }
  339.  
  340.     if (!foundIt)
  341.         {
  342.     fprintf(stderr, "ADDING A NEW TANK %d %f %f %f %f %d \n", number, x, z, finRange, speed, type);
  343.  
  344.         temptank = (struct tank *) amalloc(sizeTank, arena);
  345.  
  346.         temptank->goforit       = NULL;
  347.         
  348.         temptank->number        = number;
  349.         temptank->x             = x + globalxshift;;
  350.         temptank->y             = -1;
  351.         temptank->z             = z + globalxshift;;
  352.  
  353.         temptank->xv            = 0;
  354.         temptank->zv            = 0;
  355.         temptank->range         = 3;
  356.         temptank->rad           = 0;
  357.         temptank->theta         = 0;
  358.         temptank->count         = 0;
  359.  
  360.         temptank->finalR        = finRange;
  361.         temptank->damage        = 1;
  362.         
  363.         temptank->minrange      = 0.5;
  364.         temptank->speed         = speed;
  365.         temptank->type          = (char) type;
  366.     
  367.         temptank->next  = tanklist->next;
  368.         tanklist->next  = temptank;
  369.         }
  370.     }
  371.  
  372.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  373.  
  374. void updateNetworkTank(char * recvline, struct tank * tanklist)
  375.     {
  376.     char command[MAXLINE];
  377.     float x, z;
  378.     int number, maserCount;
  379.     struct tank * temptank, * foundtank;
  380.     int foundIt;
  381.     
  382.     sscanf(recvline, "%s %d %f %f %d",
  383.         command, &number, &x, &z, &maserCount);
  384.  
  385. /* this should have somethin that uses the monsters current location to modify the
  386.  * location of the tank
  387.  */
  388.     
  389.     foundIt = 0;
  390.     for (temptank = tanklist->next; (temptank != NULL) && (!foundIt); temptank = temptank->next)
  391.         {
  392.         if (number == temptank->number)
  393.             {
  394.             foundIt = 1;
  395.             foundtank = temptank;
  396.             }
  397.         }
  398.  
  399.     if (foundIt)
  400.         {
  401. /*
  402.         fprintf(stderr, "%s \n", recvline);
  403.         fprintf(stderr, "UPDATING TANK %d %f %f %f %d \n", number, x, y, z, maserCount);
  404. */
  405.         foundtank->x    = x + globalxshift;
  406.         foundtank->z    = z + globalzshift;
  407.         
  408.         if (maserCount > 1)
  409.             foundtank->maserCount = 10;
  410.         }
  411.     }
  412.  
  413.  
  414.   /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  415.  
  416. void tellAboutAllTanks(struct sockaddr_in * cli, int length
  417.     , struct tank * tanklist)
  418.     {
  419.     char mesg[MAXLINE];
  420.     
  421.     struct tank * tempTank;
  422.  
  423.     for (tempTank = tanklist->next; tempTank != NULL; tempTank = tempTank->next)
  424.         {
  425.         fprintf(stderr, "sending FULL data on tank %d to a new client\n", tempTank->number);
  426.  
  427. /* nother copy of this elsewhere */
  428.  
  429.         sprintf(mesg, "%s %d %3.1f %3.1f %3.1f %0.3f %d %d #", MESG_NEW_TANK,
  430.                                                  tempTank->number, 
  431.                                                  tempTank->x-globalxshift, 
  432.                                                  tempTank->z-globalzshift, 
  433.                                                  tempTank->finalR,
  434.                                                  tempTank->speed,
  435.                                                  tempTank->type, 
  436.                                                  tempTank->maserCount
  437.                                                  );
  438.  
  439.         sendMessage(mesg, cli, length);
  440.         }
  441.     }
  442.  
  443.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  444.  
  445. void updateNetworkMonsters(char * recvline, long clientFrom, void * arena)
  446.     {
  447.     struct targetInfo * tempTarget,  *thaOne;
  448.     
  449.     float n_energy, n_x, n_z;
  450.     int n_frame;
  451.     int n_monsterType, n_dead, n_beamOn;
  452.     int n_horzrot, n_vertrot, n_timeDead; 
  453.     int exists;
  454.     char command[MAXLINE];
  455.  
  456.     sscanf(recvline, "%s %d %d %f %d %d %d %f %f %d %d",
  457.             command,
  458.             &n_frame,
  459.             &n_monsterType, 
  460.             &n_energy, 
  461.             &n_horzrot, 
  462.             &n_vertrot, 
  463.             &n_dead, 
  464.             &n_x, 
  465.             &n_z, 
  466.             &n_beamOn,
  467.             &n_timeDead 
  468.             );
  469.     
  470.     exists = 0;
  471.     for(tempTarget = targets; tempTarget != NULL; tempTarget=tempTarget->next)
  472.         {
  473.         if (tempTarget->net_clientFrom == clientFrom)
  474.             {
  475.             exists = 1;
  476.             thaOne = tempTarget;
  477.             }
  478.         }
  479.  
  480.     if (exists && (thaOne->monster.monster == n_monsterType))
  481.         {       
  482.         /*****************************************************************/
  483.         /* update the values in the currently existing networked monster */
  484.         /*****************************************************************/
  485.  
  486.         thaOne->net_headHorzRotate      = n_horzrot;
  487.         thaOne->net_headVertRotate      = n_vertrot;
  488.         thaOne->net_energyRemaining     = n_energy;
  489.         thaOne->net_x                   = n_x + globalxshift;
  490.         thaOne->net_z                   = n_z + globalzshift;
  491.         thaOne->net_beamOn              = n_beamOn;
  492.         }
  493.     else if (n_timeDead < 40)
  494.         {
  495.         /*******************************/
  496.         /* add a new networked monster */
  497.         /*******************************/
  498.         
  499.         addNetworkTarget(clientFrom, n_monsterType, n_horzrot, n_vertrot, 
  500.             n_energy, n_x + globalxshift, n_z + globalzshift, n_beamOn, arena);
  501.         }
  502.     }
  503.  
  504. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  505.  
  506. void addNetworkTarget(long fromNum, int monsterType, float horz, float vert, 
  507.                         float energy, float x, float z, int beamOn, void * arena)
  508.     {
  509.     struct monsterInfo newMonster;
  510.     struct targetInfo * nother, *temp;
  511.     int alreadyExists;
  512.     int i;
  513.  
  514.     alreadyExists = 0;
  515.     for (i=0, temp=targets->next; temp != NULL; i++,temp=temp->next)
  516.         {
  517.         if (temp->net_clientFrom == fromNum)
  518.             {
  519.             alreadyExists = 1;
  520.             
  521.             /******************************/
  522.             /* monster type has changed ! */
  523.             /******************************/
  524.             
  525.             newMonster.monster  = monsterType;
  526.             newMonster          = resetMonsterParameters(newMonster);
  527.             
  528.             temp->monster               = newMonster;
  529.  
  530.             temp->net_clientFrom        = fromNum;
  531.             temp->net_headHorzRotate    = horz;
  532.             temp->net_headVertRotate    = vert;
  533.             temp->net_energyRemaining   = energy;
  534.             temp->net_x                 = x;
  535.             temp->net_z                 = z;
  536.             temp->net_beamOn            = beamOn;
  537.  
  538.             temp->monster.headHorzRotate = horz;
  539.             temp->monster.headVertRotate = vert;
  540.             temp->x = x;
  541.             temp->z = z;
  542.  
  543.             printf("updating a remote monster that has changed its type\n");
  544.             }
  545.         }
  546.  
  547.     /************************************/
  548.     /* add a new monster into this game */
  549.     /************************************/
  550.  
  551.     if (!alreadyExists)
  552.         {
  553.         newMonster.monster  = monsterType;
  554.         newMonster          = resetMonsterParameters(newMonster);
  555.     
  556.         nother = (struct targetInfo *) amalloc(sizeof(struct targetInfo), arena);
  557.         
  558.         if (nother != NULL)
  559.             {
  560.             nother->monster             = newMonster;
  561.             nother->net_clientFrom      = fromNum;
  562.             nother->net_headHorzRotate  = horz;
  563.             nother->net_headVertRotate  = vert;
  564.             nother->net_energyRemaining = energy;
  565.             nother->net_x               = x;
  566.             nother->net_z               = z;
  567.             nother->net_beamOn          = beamOn;
  568.  
  569.             nother->monster.headHorzRotate = horz;
  570.             nother->monster.headVertRotate = vert;
  571.             nother->x = x;
  572.             nother->z = z;
  573.  
  574.             nother->next    = targets->next;
  575.             targets->next   = nother;
  576.             }
  577.         }
  578.     }
  579.  
  580. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  581.  
  582. void updateClientMonster(char * recvline, void * arena)
  583.     {
  584.     struct targetInfo * tempTarget,  *thaOne;
  585.     
  586.     float n_energy, n_x, n_z;
  587.     int n_frame;
  588.     int n_monsterType, n_dead, n_beamOn;
  589.     int n_horzrot, n_vertrot, n_timeDead; 
  590.     int exists;
  591.     long recvfrom;
  592.     char command[MAXLINE];
  593.     char orig_command[MAXLINE];
  594.  
  595.     sscanf(recvline, "%s %ld %s %d %d %f %d %d %d %f %f %d %d",
  596.             command,
  597.             &recvfrom,
  598.             orig_command, 
  599.             &n_frame,
  600.             &n_monsterType, 
  601.             &n_energy, 
  602.             &n_horzrot, 
  603.             &n_vertrot, 
  604.             &n_dead, 
  605.             &n_x, 
  606.             &n_z, 
  607.             &n_beamOn,
  608.             &n_timeDead 
  609.             );
  610.     
  611.     exists = 0;
  612.     for(tempTarget = targets; tempTarget != NULL; tempTarget=tempTarget->next)
  613.         {                                 /* note difference here ! */
  614.         if (tempTarget->net_clientFrom == recvfrom)
  615.             {
  616.             exists = 1;
  617.             thaOne = tempTarget;
  618.             }
  619.         }
  620.  
  621.     if (exists && (thaOne->monster.monster == n_monsterType))
  622.         {       
  623.         /*****************************************************************/
  624.         /* update the values in the currently existing networked monster */
  625.         /*****************************************************************/
  626.  
  627.         thaOne->net_headHorzRotate      = n_horzrot;
  628.         thaOne->net_headVertRotate      = n_vertrot;
  629.         thaOne->net_energyRemaining     = n_energy;
  630.         thaOne->net_x                   = n_x + globalxshift;
  631.         thaOne->net_z                   = n_z + globalzshift;
  632.         thaOne->net_beamOn              = n_beamOn;
  633.         }
  634.     else if (n_timeDead < 40)
  635.         {
  636.         /*******************************/
  637.         /* add a new networked monster */
  638.         /*******************************/
  639.         
  640.         addNetworkTarget(recvfrom, n_monsterType, n_horzrot, n_vertrot, 
  641.             n_energy, n_x + globalxshift, n_z + globalzshift, n_beamOn, arena);
  642.         }
  643.     }
  644.  
  645. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  646.  
  647. int sendMessage(char * mesg,  struct sockaddr_in * cli, int length)
  648.     {
  649.     int n;
  650.       
  651.     n = strlen(mesg)+1;
  652.  
  653.     if (sendto(sockfd, mesg, n, 0, (struct sockaddr *) cli, length) != n)
  654.         {
  655.         printf("Sendto error\n");
  656.         return(1);
  657.         }
  658.     else
  659.         return(0);
  660.     }
  661.     
  662.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  663.    
  664. void processClient(time_t now, int mainCounter, int totalCounter,
  665.     struct tree * treelist, struct tank * tanklist, void * arena,
  666.     int sizeTank, struct monsterInfo Googelon,
  667.     int buildingBoomThisFrameCounter, int buildingBoomThisFrame[20])
  668.     {
  669.     char recvline[MAXLINE];
  670.     char mesg[MAXLINE];
  671.     char command[MAXLINE];
  672.     int n;
  673.     int servlen;
  674.     long clientFrom;
  675.     int j;
  676.     int frameNum;
  677.  
  678.     extern int errno;
  679.      
  680.  
  681.     /* send a request every once in a while until connection established */
  682.     /* if I haven't seen any data from the server in a while try to reconnect */
  683.     /* this may be a bit harsh to say connected = 0 */
  684.  
  685.     if (now > (lastRecvTime + RECONNECT_TIME))
  686.         connected = 0;
  687.  
  688.     if (!connected) 
  689.         {
  690.         sprintf(mesg,MESG_REQUEST);
  691.         sendMessage(mesg, &serv_addr, sizeof(serv_addr));
  692.         }
  693.  
  694.     if (now > (lastNotDeadYetTime + IM_NOT_DEAD_SEND_TIME))
  695.         {
  696.         lastNotDeadYetTime = now;
  697.  
  698.         sprintf(mesg,MESG_NOTDEADYET);
  699.         sendMessage(mesg, &serv_addr, sizeof(serv_addr));
  700.         }
  701.  
  702.         /*******************************************************/
  703.         /* tell all the clients when a tree has been destroyed */
  704.         /*******************************************************/
  705.  
  706.  
  707.         for(j=0;j<buildingBoomThisFrameCounter;j++)
  708.             {
  709.             sprintf(mesg, "%s %d #", MESG_BUILDING, buildingBoomThisFrame[j]);
  710.  
  711.             sendMessage(mesg, &serv_addr, sizeof(serv_addr));
  712.             }
  713.  
  714.         /***********************************/
  715.         /* ocassionally send to the server */
  716.         /***********************************/
  717.  
  718.         if (!(mainCounter % MONSTER_UPDATE_RATE))
  719.             {
  720.             sprintf(mesg, "%s %1d %1d %1.0f %1d %1d %1d %1.1f %1.1f %1d %1d#",
  721.                             MESG_UPDATE, 
  722.                             totalCounter, 
  723.                             Googelon.monster, 
  724.                             Googelon.energyRemaining, 
  725.                             Googelon.headHorzRotate,
  726.                             Googelon.headVertRotate,
  727.                             Googelon.monsterIsDead, 
  728.                             -globalxshift, 
  729.                             -globalzshift, 
  730.                             beamOnSinceLast, 
  731.                             Googelon.timeDead
  732.                             );
  733.  
  734.             beamOnSinceLast = 0;
  735.             sendMessage(mesg, &serv_addr, sizeof(serv_addr));
  736.             }
  737.  
  738.     
  739.         /*************************************/
  740.         /* wait for messages from the server */
  741.         /*************************************/
  742.  
  743.          servlen = sizeof(serv_addr);
  744. #ifndef AMIGAVERSION
  745.          n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *) &serv_addr, (int *)& servlen);
  746. #else
  747.          n = recvfrom(sockfd, (UBYTE *)recvline, MAXLINE, 0,
  748.                       (struct sockaddr *)&serv_addr, (LONG *)&servlen);
  749. #endif
  750.          if ((n < 0)  && (errno != EWOULDBLOCK))
  751.             {
  752.             printf("Client receive error\n");
  753.             }
  754.         else if (n >= 0)
  755.             {
  756.             clientFrom = ntohl(serv_addr.sin_addr.s_addr);
  757. /*
  758.             printf("RECEIVED: %s",recvline);
  759.             printf("FROM: %ld\n\n",clientFrom);
  760. */
  761.             connected = 1;
  762.             lastRecvTime = now;
  763.             
  764.             sscanf(recvline, "%s %d", command, &frameNum);
  765.             if (strcmp(command, MESG_UPDATE) == 0)
  766.                 {
  767.                 /*if (frameNum > lastMonsterUpdate) */
  768.                 /* took this out since there can be > 1 monster being sent
  769.                  * to the client
  770.                  */
  771.                     {
  772.                     updateNetworkMonsters(recvline, clientFrom, arena);
  773.                     lastMonsterUpdate = frameNum;
  774.                     }
  775.                 }
  776.  
  777.             if (strcmp(command, MESG_NEW_TANK) == 0)
  778.                 {
  779.                 addNewNetworkTank(recvline, tanklist, arena, sizeTank);
  780.                 }
  781.  
  782.             if (strcmp(command, MESG_UPDATE_TANK) == 0)
  783.                 {
  784.                 updateNetworkTank(recvline, tanklist);
  785.                 }
  786.             if (strcmp(command, MESG_BUILDING) == 0)
  787.                 {
  788.                 updateNetworkBuildings(recvline, treelist);
  789.                 }
  790.             if (strcmp(command, MESG_CLIENT_CLIENT_UPDATE) == 0)
  791.                 {
  792.                 updateClientMonster(recvline, arena);
  793.                 }
  794.             }
  795.                     
  796. /*      close(sockfd); */
  797.  
  798.     }
  799.  
  800.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  801.  
  802. void tellAboutAllDeadBuildings(struct sockaddr_in * cli, int length, 
  803.                                int buildingBoomSoFarCounter, 
  804.                                int buildingBoomSoFar[800])
  805.     {
  806.     int j;
  807.     char mesg[MAXLINE];
  808.  
  809.     for(j=0; j<buildingBoomSoFarCounter; j++)
  810.         {
  811.         sprintf(mesg, "%s %d #", MESG_BUILDING,  buildingBoomSoFar[j]);
  812.  
  813.         sendMessage(mesg, cli, length);
  814.         }
  815.     }
  816.     
  817.  /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  818.   
  819.   /* there is now a connected = 0 in setPlayConditions!!! */
  820.    
  821. void processNetwork(time_t now, int mainCounter, int totalCounter,
  822.     struct tree * treelist, struct tank * tanklist, void * arena, 
  823.     struct monsterInfo Googelon, int buildingBoomSoFarCounter, 
  824.     int buildingBoomThisFrameCounter, int buildingBoomSoFar[800], 
  825.     int buildingBoomThisFrame[20])
  826.     {
  827.     long recvFrom;
  828.     struct sockaddr_in cli_addr;
  829.     char recvline[MAXLINE];
  830.     char mesg[MAXLINE];
  831.     char command[MAXLINE];
  832.  
  833.     struct targetInfo * tempTarget;
  834.     extern int errno;
  835.     
  836.     int clilen;
  837.     int oldClient;
  838.     int n;
  839.     int i, j;
  840.     int gotOne;
  841.     int noMore;
  842.     int thisClient;
  843.     int frameNumber;
  844.     
  845.     clilen = sizeof(cli_addr);
  846.  
  847.     noMore = 0;
  848.     
  849.     tankModulator = (tankModulator + 1) % MONSTER_UPDATE_RATE;
  850.     
  851.     while(!noMore)
  852.         {
  853.         /**********************/
  854.         /* Read incoming data */
  855.         /**********************/
  856.          
  857. #ifndef AMIGAVERSION
  858.         n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *) &cli_addr, (int *)& clilen);
  859. #else
  860.         n = recvfrom(sockfd, (UBYTE *)recvline, MAXLINE, 0,
  861.                      (struct sockaddr *)&cli_addr, (LONG *)&clilen);
  862. #endif
  863.     
  864.         if (n < 0)
  865.             if(errno != EWOULDBLOCK)
  866.                 {
  867.                 printf("Server recvfrom error\n");
  868.                 noMore = 1;
  869.                 }
  870.             else
  871.                 {
  872.                 noMore = 1;
  873.                 }
  874.         else
  875.             {
  876.             recvFrom = ntohl(cli_addr.sin_addr.s_addr);
  877. /*
  878.             printf("RECEIVED: %s",recvline);
  879.             printf(" FROM: %ld\n\n",recvFrom);
  880. */
  881.  
  882.             thisClient = -1;
  883.             
  884.             for(i=0; i<numClients; i++)
  885.                 if (recvFrom == clientsFrom[i])
  886.                     {
  887.                     thisClient = i;
  888.                     }
  889.  
  890.             /* its possible we are getting an update message from a
  891.             client we didn't know we had (if server crashes) so we
  892.             ignore all of these messages until it establishes a
  893.             'proper' connection */
  894.                 
  895.             if (thisClient != -1)
  896.                 {
  897.                 if (strcmp(recvline,MESG_NOTDEADYET) == 0)      
  898.                     {
  899.                     clientsAlive[thisClient] = now;
  900.                     }
  901.     
  902.                 sscanf(recvline, "%s %d", command, &frameNumber);
  903.                 if (strcmp(command, MESG_UPDATE) == 0)
  904.                     {
  905.                     if (frameNumber > lastClientMonsterUpdate[thisClient])
  906.                         {
  907.                         updateNetworkMonsters(recvline, recvFrom, arena);
  908.                         lastClientMonsterUpdate[thisClient] = frameNumber;
  909.                         
  910.                         /*******************************************/
  911.                         /* send this info to all the other clients */
  912.                         /*******************************************/
  913.                         
  914.                         sprintf(mesg, "%s %ld %s", MESG_CLIENT_CLIENT_UPDATE, recvFrom, recvline);
  915.                         
  916.                         for(i=0; i<numClients; i++)
  917.                             if (i != thisClient)
  918.                                 {
  919.                                 sendMessage(mesg, &clients[i], sizeof(clients[i]));
  920.                                 /* fprintf(stderr, "%s\n", mesg); */
  921.                                 }
  922.                         }
  923.                     }
  924.                 }
  925.     
  926.             if (strcmp(command, MESG_BUILDING) == 0)
  927.                 {
  928.                 updateNetworkBuildings(recvline, treelist);
  929.                 }
  930.  
  931.     
  932.             if (strcmp(recvline,MESG_REQUEST) == 0)
  933.                 {
  934.                 /*********************************************/
  935.                 /* need to see if this client already exists */
  936.                 /*********************************************/
  937.                 
  938.                 oldClient = 0;
  939.                 
  940.                 for(i=0; i<numClients; i++)
  941.                     {  
  942.                     if (recvFrom == clientsFrom[i])
  943.                         {
  944.                         clients[i]      = cli_addr;
  945.                         clientsAlive[i] = now;
  946.                         oldClient       = 1;
  947.                         }
  948.                     }
  949.  
  950.                 if (oldClient)
  951.                     {
  952.                     sprintf(mesg,MESG_REAQUIRE);
  953.                     sendMessage(mesg, &cli_addr, clilen);
  954.  
  955.                     tellAboutAllDeadBuildings(&cli_addr, clilen, buildingBoomSoFarCounter, buildingBoomSoFar);
  956.                     tellAboutAllTanks(&cli_addr, clilen, tanklist);
  957.  
  958.                     }
  959.                     
  960.                 if (!oldClient)
  961.                     {
  962.                     clients[numClients]         = cli_addr;
  963.                     clientsFrom[numClients]     = recvFrom;
  964.                     clientsAlive[numClients]    = now;
  965.                     
  966.                     numClients++;
  967.                     
  968.                     sprintf(mesg, MESG_ACKNOWLEDGE);
  969.                     sendMessage(mesg, &cli_addr, clilen);
  970.  
  971.                     tellAboutAllDeadBuildings(&cli_addr, clilen, buildingBoomSoFarCounter, buildingBoomSoFar);
  972.                     tellAboutAllTanks(&cli_addr, clilen, tanklist);
  973.                     }
  974.                 }
  975.     
  976.             }
  977.  
  978.         }
  979.     
  980.         /****************************************************************/
  981.         /* kill any client connection that has not responded in a while */
  982.         /****************************************************************/
  983.  
  984.         i = 0;
  985.         gotOne = 0;
  986.         
  987.         while ((i < numClients) && (!gotOne))
  988.             {  
  989.             if ((clientsAlive[i]+IM_NOT_DEAD_YET_TIME) < now)
  990.                 {
  991.                 printf("killing client %d\n", i);
  992.  
  993.                 /* remove the appropriate target */
  994.                 for(tempTarget = targets; tempTarget != NULL; tempTarget=tempTarget->next)
  995.                     {
  996.                     if (tempTarget->net_clientFrom == clientsFrom[i])
  997.                         tempTarget->net_energyRemaining = 0;
  998.                     }
  999.  
  1000.                 for (j=i+1; j < numClients; j++)
  1001.                     {
  1002.                     clients[j-1]        = clients[j];
  1003.                     clientsFrom[j-1]    = clientsFrom[j];
  1004.                     clientsAlive[j-1]   = clientsAlive[j];
  1005.                     gotOne = 1;
  1006.                     }
  1007.                 numClients -= 1;
  1008.                 
  1009.                 }
  1010.             else
  1011.                 i++;
  1012.             }
  1013.  
  1014.         /*******************************************************/
  1015.         /* tell all the clients when a tree has been destroyed */
  1016.         /*******************************************************/
  1017.  
  1018.         for(j=0;j<buildingBoomThisFrameCounter;j++)
  1019.             {
  1020.             sprintf(mesg, "%s %d #", MESG_BUILDING, buildingBoomThisFrame[j]);
  1021.  
  1022.             for(i=0; i<numClients; i++)
  1023.                 sendMessage(mesg, &clients[i], sizeof(clients[i]));
  1024.             }
  1025.  
  1026.  
  1027.  
  1028.         /*************************************************************/
  1029.         /* ocassionally broadcast to all currently connected clients */
  1030.         /*************************************************************/
  1031.  
  1032.         if (!(mainCounter % MONSTER_UPDATE_RATE))
  1033.             {
  1034.             sprintf(mesg, "%s %1d %1d %1.0f %1d %1d %1d %1.1f %1.1f %1d %1d#",
  1035.                             MESG_UPDATE, 
  1036.                             totalCounter, 
  1037.                             Googelon.monster, 
  1038.                             Googelon.energyRemaining, 
  1039.                             Googelon.headHorzRotate,
  1040.                             Googelon.headVertRotate,
  1041.                             Googelon.monsterIsDead, 
  1042.                             -globalxshift, 
  1043.                             -globalzshift, 
  1044.                             beamOnSinceLast, 
  1045.                             Googelon.timeDead
  1046.                             );
  1047.  
  1048.             beamOnSinceLast = 0;
  1049.  
  1050.             for(i=0;i<numClients;i++)
  1051.                 sendMessage(mesg, &clients[i], sizeof(clients[i]));
  1052.             }
  1053. }
  1054.