home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Issue 2 / Freelog_HS_3_Setp_Oct_Nov_2000_CD2.mdx / Arcade / Orbit / src / client.c < prev    next >
C/C++ Source or Header  |  1999-09-27  |  21KB  |  1,138 lines

  1. /*
  2.  
  3. ORBIT, a freeware space combat simulator
  4. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20. */
  21.  
  22. #include "orbit.h"
  23.  
  24. #ifndef WIN32
  25. #include <sys/socket.h>
  26. #include <unistd.h>
  27. #include <netinet/in.h>
  28. #include <netdb.h>
  29. #include <arpa/inet.h>
  30. #endif
  31.  
  32. #include <limits.h>
  33. #include <fcntl.h>
  34. #include <errno.h>
  35. #include <stdarg.h>
  36.  
  37. /*
  38.  *  All sorts of stuff a client needs
  39.  */
  40.  
  41. int FindClient()
  42. /*
  43.  *  Find an unused client
  44.  */
  45. {
  46.     int c;
  47.  
  48.     for (c=0; c<NCLIENTS; c++)
  49.     {
  50.         if (!client[c].active)
  51.         {
  52.             client[c].active = 1;
  53.             return c;
  54.         }
  55.     }
  56.  
  57.     /* Ran out */
  58.     return (-1);
  59. }
  60.  
  61. DoClient()
  62. /*
  63.  *  Handle ORBIT client duties
  64.  */
  65. {
  66.     char buf[1024];
  67.     int r, e;
  68.  
  69.     /* Bump timers */
  70.     clientme.timer.server += deltaT;
  71.     clientme.timer.pos += deltaT;
  72.  
  73.     /* If server has been idle too long, goodbye */
  74.     if (clientme.timer.server > MAXSERVERIDLE)
  75.     {
  76.         Mprint ("Server is not responding");
  77.         Log ("DoClient: Dropping idle server");
  78. #ifndef WIN32
  79.         close (clientme.socket);
  80. #else
  81.         closesocket (clientme.socket);
  82. #endif
  83.         am_client = 0;
  84.         return;
  85.     }
  86.  
  87.     /* Time to report position? */
  88.     if (clientme.timer.pos >= CLIENTPOSINTERVAL)
  89.     {
  90.         ReportPosition();
  91.         clientme.timer.pos = 0.0;
  92.     }
  93.  
  94.     /* Try to read from the server */
  95.     r = recv (clientme.socket, buf, 1024, 0);
  96.  
  97.     /* If recv returns zero the other side has gone away */
  98.     if (r == 0)
  99.     {
  100.         Mprint ("Dropped by server");
  101.         Log ("DoClient: Dropped by server");
  102. #ifndef WIN32
  103.         close (clientme.socket);
  104. #else
  105.         closesocket (clientme.socket);
  106. #endif
  107.         am_client = 0;
  108.  
  109.         InitNetwork();
  110.         InitTargets();
  111.  
  112.         return;
  113.     }
  114.  
  115.     /* If we get an error it better be EWOULDBLOCK */
  116. #ifndef WIN32
  117.     if (r < 0)
  118.     {
  119.         if (errno == EWOULDBLOCK)
  120.         {
  121.             /* All is well, no data from server */
  122.             return;
  123.         }
  124.         else
  125.         {
  126.             /* Uh oh */
  127.             Log ("DoClient: recv() error: %d", errno);
  128.             return;
  129.         }
  130.     }
  131. #else
  132.     if (r == SOCKET_ERROR)
  133.     {
  134.         e = WSAGetLastError();
  135.         if (e == WSAEWOULDBLOCK)
  136.         {
  137.             /* All is well, no data from server */
  138.             return;
  139.         }
  140.         else
  141.         {
  142.             /* Uh oh */
  143.             Log ("DoClient: recv() error: %d", e);
  144.             return;
  145.         }
  146.     }
  147. #endif
  148.  
  149.     /* We really have data from the server! */
  150.     clientme.timer.server = 0.0;
  151.  
  152.     /* Handle the data */
  153.     buf[r] = 0;
  154.     recv_bytes += r;
  155. /*    Log ("DoClient: Server data: %s", buf);    */
  156.  
  157.     ServerData (buf, r);
  158. }
  159.  
  160. ServerData (buf, n)
  161. int n;
  162. char *buf;
  163. /*
  164.  *  Separate incoming data into packets
  165.  */
  166. {
  167.     int i;
  168. #ifndef BINARYPACKETS
  169.     int ch, j;
  170. #endif
  171.  
  172. #ifdef BINARYPACKETS
  173.     for (i=0; i<n; i++) ServerByte (buf[i]);
  174.  
  175. #else
  176.     j = clientme.ptr;
  177.  
  178.     for (i=0; i<n; i++)
  179.     {
  180.         ch = clientme.pkt[j] = buf[i];
  181.         j = (j + 1) % 1024;
  182.  
  183.         /* Got a packet? */
  184.         if (ch == 0)
  185.         {
  186.             ServerPacket (clientme.pkt);
  187.             j = 0;
  188.         }
  189.     }
  190.  
  191.     clientme.ptr = j;
  192. #endif
  193. }
  194.  
  195. ServerByte (c)
  196. char c;
  197. /*
  198.  *  Process one byte from server
  199.  */
  200. {
  201.     switch (clientme.state)
  202.     {
  203.     case NETSTATE_MAGIC:
  204.         if (c == NET_MAGIC)
  205.         {
  206.             clientme.state = NETSTATE_SIZE;
  207.         }
  208.         break;
  209.  
  210.     case NETSTATE_SIZE:
  211.         clientme.remain = 0xff & c;
  212.         clientme.ptr = 0;
  213.         clientme.state = NETSTATE_PACKET;
  214.         if (clientme.remain == 0) clientme.state = NETSTATE_MAGIC;
  215.         break;
  216.  
  217.     case NETSTATE_PACKET:
  218.         clientme.pkt[clientme.ptr++] = c;
  219.         clientme.remain--;
  220.         if (clientme.remain == 0)
  221.         {
  222.             clientme.pkt[clientme.ptr] = 0;
  223.             ServerPacket (clientme.pkt);
  224.             clientme.state = NETSTATE_MAGIC;
  225.         }
  226.         break;
  227.  
  228.     default:
  229.         Log ("ServerByte: PANIC! No such state: %d", clientme.state);
  230.         break;
  231.     }
  232. }
  233.  
  234. ServerPacket (pkt)
  235. char *pkt;
  236. /*
  237.  *  Handle a packet from the server
  238.  */
  239. {
  240.     char cmd[128];
  241.  
  242.     /* If high bit of first byte is set, this is a binary packet */
  243.     if (0x80 & pkt[0])
  244.     {
  245.         ServerBinaryPacket (pkt);
  246.         return;
  247.     }
  248.  
  249.     /* Sanity check on packet */
  250.     if ( (strlen(pkt) == 0) ||
  251.          (pkt[0] == ' ') ||
  252.          (pkt[0] == '\r') ||
  253.          (pkt[0] == '\n') ||
  254.          (pkt[0] == '\t') )
  255.     {
  256.         Log ("ServerPacket: Insane packet: %s", pkt);
  257.         return;
  258.     }
  259.  
  260.     /* Extract command part */
  261.     sscanf (pkt, "%s", cmd);
  262.  
  263.     /* Dispatch */
  264.     if (!strcasecmp (cmd, "poss"))
  265.     {
  266.         ServerPositionShort (pkt);
  267.         return;
  268.     }
  269.     else if (!strcasecmp (cmd, "posl"))
  270.     {
  271.         ServerPositionLong (pkt);
  272.         return;
  273.     }
  274.     else if (!strcasecmp (cmd, "ping"))
  275.     {
  276.         ServerPing (pkt);
  277.         return;
  278.     }
  279.     else if (!strcasecmp (cmd, "fire"))
  280.     {
  281.         ServerFire (pkt);
  282.         return;
  283.     }
  284.     else if (!strcasecmp (cmd, "mhit"))
  285.     {
  286.         ServerMHit (pkt);
  287.         return;
  288.     }
  289.     else if (!strcasecmp (cmd, "mdie"))
  290.     {
  291.         ServerMDie (pkt);
  292.         return;
  293.     }
  294.     else if (!strcasecmp (cmd, "mesg"))
  295.     {
  296.         ServerMessage (pkt);
  297.         return;
  298.     }
  299.     else if (!strcasecmp (cmd, "name"))
  300.     {
  301.         ServerName (pkt);
  302.         return;
  303.     }
  304.     else if (!strcasecmp (cmd, "vcnt"))
  305.     {
  306.         ServerVacant (pkt);
  307.         return;
  308.     }
  309.     else if (!strcasecmp (cmd, "modl"))
  310.     {
  311.         ServerModel (pkt);
  312.         return;
  313.     }
  314.     else if (!strcasecmp (cmd, "flag"))
  315.     {
  316.         ServerFlag (pkt);
  317.         return;
  318.     }
  319.     else if (!strcasecmp (cmd, "crat"))
  320.     {
  321.         ServerCrater (pkt);
  322.         return;
  323.     }
  324.     else if (!strcasecmp (cmd, "cmsg"))
  325.     {
  326.         ServerCMSG (pkt);
  327.         return;
  328.     }
  329.     else if (!strcasecmp (cmd, "helo"))
  330.     {
  331.         ServerHelo (pkt);
  332.         return;
  333.     }
  334.     else if (!strcasecmp (cmd, "gbye"))
  335.     {
  336.         ServerGbye (pkt);
  337.         return;
  338.     }
  339.     else if (!strcasecmp (cmd, "welc"))
  340.     {
  341.         ServerWelcome (pkt);
  342.         return;
  343.     }
  344.     else if (!strcasecmp (cmd, "plan"))
  345.     {
  346.         ServerPlanet (pkt);
  347.         return;
  348.     }
  349.     else if (!strcasecmp (cmd, "rpln"))
  350.     {
  351.         ServerResetPlanets (pkt);
  352.         return;
  353.     }
  354.     else
  355.     {
  356.         Log ("ServerPacket: Unrecongized command: %s", cmd);
  357.         return;
  358.     }
  359. }
  360.  
  361. ServerPing (pkt)
  362. char *pkt;
  363. /*
  364.  *  Handle ping packet from server
  365.  */
  366. {
  367.     /* Just send it right back */
  368.     SendASCIIPacket (clientme.socket, pkt);
  369. }
  370.  
  371. ServerBinaryPing (pkt)
  372. char *pkt;
  373. /*
  374.  *  Handle binary ping packet
  375.  */
  376. {
  377.     double t;
  378.  
  379.     /* Decode */
  380.     DecodeBinaryPacket (pkt, "F", &t);
  381.  
  382.     /* Echo */
  383.     SendBinaryPacket (clientme.socket, "cF", PKT_PING, t);
  384. }
  385.  
  386. ServerMessage (pkt)
  387. char *pkt;
  388. /*
  389.  *  Text message from server
  390.  */
  391. {
  392.     /* Print it to the screen */
  393.     if ( (pkt[4] != 0) && (pkt[5] != 0) )
  394.     {
  395.         Mprint (&pkt[5]);
  396.     }
  397. }
  398.  
  399. ServerWelcome (pkt)
  400. char *pkt;
  401. /*
  402.  *  Server says hello and gives us our client number
  403.  */
  404. {
  405.     int i, t;
  406.  
  407.     /* Extract client number */
  408.     if (1 != sscanf (pkt, "%*s %d", &i)) return;
  409.  
  410.     /* Set up our client */
  411.     Log ("ServerWelcome: I am client %d", i);
  412.     clientme.client = i;
  413.  
  414.     /* Set up client and target */
  415.     client[i].active = 1;
  416.     client[i].is_me = 1;
  417.     client[i].frags = 0;
  418.     t = client[i].target = InitClientTarget();
  419.     strcpy (target[t].name, player.name);
  420.     target[t].hidden = target[t].invisible = 1;
  421. }
  422.  
  423. ReportPosition()
  424. /*
  425.  *  Report my position
  426.  */
  427. {
  428. #ifdef BINARYPACKETS
  429.     int c;
  430. #else
  431.     char cmd[5];
  432. #endif
  433.  
  434.     /* Not if we're dead */
  435.     if ( (state == STATE_DEAD1) || (state == STATE_DEAD2) ) return;
  436.  
  437.     /* Urgent? */
  438.     if (clientme.urgent)
  439.     {
  440. #ifdef BINARYPACKETS
  441.         c = PKT_POSU;
  442. #else
  443.         strcpy (cmd, "POSU");
  444. #endif
  445.         clientme.urgent = 0;
  446.     }
  447.     else
  448.     {
  449. #ifdef BINARYPACKETS
  450.         c = PKT_POSN;
  451. #else
  452.         strcpy (cmd, "POSN");
  453. #endif
  454.     }
  455.  
  456. #ifdef BINARYPACKETS
  457.     SendBinaryPacket (clientme.socket, "cVVvvffffff", c,
  458.         player.pos, player.vel, player.view, player.up,
  459.         player.move_up, player.move_down,
  460.         player.move_right, player.move_left,
  461.         player.move_pitchright, player.move_pitchleft);
  462. #else
  463.     SendASCIIPacket (clientme.socket,
  464.         "POSN %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
  465.         player.pos[0], player.pos[1], player.pos[2],
  466.         player.vel[0], player.vel[1], player.vel[2],
  467.         player.view[0], player.view[1], player.view[2],
  468.         player.up[0], player.up[1], player.up[2],
  469.         player.move_up, player.move_down,
  470.         player.move_right, player.move_left,
  471.         player.move_pitchright, player.move_pitchleft);
  472. #endif
  473. }
  474.  
  475. ServerPositionShort (pkt)
  476. char *pkt;
  477. /*
  478.  *  The server is sending a client's short position report
  479.  */
  480. {
  481.     int c;
  482.     double pos[3], vel[3];
  483.  
  484.     /* Parse packet */
  485.     if (7 != sscanf (pkt, "%*s %d %lf %lf %lf %lf %lf %lf", &c,
  486.         &player.pos[0], &player.pos[1], &player.pos[2],
  487.         &player.vel[0], &player.vel[1], &player.vel[2]))
  488.     {
  489.         Log ("ServerPositionShort: Malformed POSS packet: %s", pkt);
  490.         return;
  491.     }
  492.  
  493.     PositionShort (c, pos, vel);
  494. }
  495.  
  496. PositionShort (c, pos, vel)
  497. int c;
  498. double pos[3], vel[3];
  499. /*
  500.  *  Process short position report
  501.  */
  502. {
  503.     int t;
  504.  
  505.     /* Sanity */
  506.     if ((c<0) || (c>=NCLIENTS)) return;
  507.  
  508.     /* Mark client active */
  509.     client[c].active = 1;
  510.  
  511.     /* Is it for me? */
  512.     if (client[c].is_me)
  513.     {
  514.         Vset (player.pos, pos);
  515.         Vset (player.vel, vel);
  516.     }
  517.     else
  518.     {
  519.         /* Not for me, see if we have target for this client */
  520.         if ((-1) == (t = client[c].target))
  521.         {
  522.             t = client[c].target = InitClientTarget();
  523.         }
  524.  
  525.         /* Make target unhidden */
  526.         target[t].hidden = 0;
  527.  
  528.         /* Set position */
  529.         Vset (target[t].pos, pos);
  530.         Vset (target[t].vel, vel);
  531.     }
  532. }
  533.  
  534. ServerPositionLong (pkt)
  535. char *pkt;
  536. /*
  537.  *  The server is sending a client's long position report
  538.  */
  539. {
  540.     int c;
  541.     double pos[3], vel[3], view[3], up[3], move_up, move_down, move_left;
  542.     double move_right, move_pitchright, move_pitchleft;
  543.  
  544.     /* Parse packet */
  545.     if (19 != sscanf (pkt, "%*s %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
  546.         &c,
  547.         &pos[0], &pos[1], &pos[2], &vel[0], &vel[1], &vel[2],
  548.         &view[0], &view[1], &view[2], &up[0], &up[1], &up[2],
  549.         &move_up, &move_down, &move_right, &move_left,
  550.         &move_pitchright, &move_pitchleft))
  551.     {
  552.         Log ("ServerPositionLong: Malformed POSL packet: %s", pkt);
  553.         return;
  554.     }
  555.  
  556.     PositionLong (c, pos, vel, view, up, move_up, move_down, move_right,
  557.         move_left, move_pitchright, move_pitchleft);
  558. }
  559.  
  560. PositionLong (c, pos, vel, view, up, move_up, move_down, move_right, move_left,
  561.     move_pitchright, move_pitchleft)
  562. int c;
  563. double pos[3], vel[3], view[3], up[3];
  564. double move_up, move_down, move_right, move_left;
  565. double move_pitchright, move_pitchleft;
  566. /*
  567.  *  Process a long position report
  568.  */
  569. {
  570.     int t;
  571.  
  572.     /* Sanity */
  573.     if ((c<0) || (c>=NCLIENTS)) return;
  574.  
  575.     /* Mark client active */
  576.     client[c].active = 1;
  577.  
  578.     /* Is it for me? */
  579.     if (client[c].is_me)
  580.     {
  581.         Vset (player.pos, pos);
  582.         Vset (player.vel, vel);
  583.         Vset (player.view, view);
  584.         Vset (player.up, up);
  585.         player.move_up = move_up;
  586.         player.move_down = move_down;
  587.         player.move_left = move_left;
  588.         player.move_right = move_right;
  589.         player.move_pitchright = move_pitchright;
  590.         player.move_pitchleft = move_pitchleft;
  591.         Crossp (player.right, player.up, player.view);
  592.     }
  593.     else
  594.     {
  595.         /* Not for me, see if we have target for this client */
  596.         if ((-1) == (t = client[c].target))
  597.         {
  598.             t = client[c].target = InitClientTarget();
  599.         }
  600.  
  601.         /* Make target unhidden */
  602.         target[t].hidden = 0;
  603.  
  604.         /* Set position */
  605.         Vset (target[t].pos, pos);
  606.         Vset (target[t].vel, vel);
  607.         Vset (target[t].view, view);
  608.         Vset (target[t].up, up);
  609.         target[t].move_up = move_up;
  610.         target[t].move_down = move_down;
  611.         target[t].move_left = move_left;
  612.         target[t].move_right = move_right;
  613.         target[t].move_pitchright = move_pitchright;
  614.         target[t].move_pitchleft = move_pitchleft;
  615.  
  616.         Normalize (target[t].up);
  617.         Normalize (target[t].view);
  618.  
  619.         Crossp (target[t].right, target[t].up, target[t].view);
  620.     }
  621. }
  622.  
  623. ServerMHit (pkt)
  624. char *pkt;
  625. /*
  626.  *  We were hit by a missile
  627.  */
  628. {
  629.     double yield;
  630.  
  631.     /* Parse packet */
  632.     if (1 != sscanf (pkt, "%*s %lf", &yield))
  633.     {
  634.         Log ("ServerMHit: Malformed MHIT packet: %s", pkt);
  635.         return;
  636.     }
  637.  
  638.     /* Flash screen red */
  639.     palette_flash = 2;
  640.  
  641.     /* Damage shields */
  642.     player.shields -= yield;
  643.     if (player.shields < 0.0) player.shields = 0.0;
  644. }
  645.  
  646. ServerMDie (pkt)
  647. char *pkt;
  648. /*
  649.  *  Someone was killed.  Hope it wasn't me!
  650.  */
  651. {
  652.     int ckiller, cvictim;
  653.     double v[3], d;
  654.  
  655.     /* Parse packet */
  656.     if (2 != sscanf (pkt, "%*s %d %d", &cvictim, &ckiller))
  657.     {
  658.         Log ("ServerMDie: Malformed MDIE packet: %s", pkt);
  659.         return;
  660.     }
  661.  
  662.     /* Adjust frags */
  663.     client[ckiller].frags++;
  664.  
  665.     /* Tell me about it */
  666.     Cprint ("%s was killed by %s",
  667.         target[client[cvictim].target].name,
  668.         target[client[ckiller].target].name);
  669.  
  670.     /* Was it me? */
  671.     if (cvictim == clientme.client)
  672.     {
  673.         Cprint ("YOU were killed!");
  674.         NetPlayerDies();
  675.     }
  676.     else
  677.     {
  678.         /* Make target hidden */
  679.         target[client[cvictim].target].hidden = 1;
  680.  
  681.         /* Make a boom if close enough */
  682.         Vsub (v, player.pos, target[client[cvictim].target].pos);
  683.         d = Mag2 (v);
  684.         if (d <= TARG_MAXRANGE2) Boom (target[client[cvictim].target].pos, 1.0);
  685.     }
  686.  
  687.     CheckLock();
  688. }
  689.  
  690. ServerCrater (pkt)
  691. char *pkt;
  692. /*
  693.  *  Someone hit a planet.  Hope it wasn't me!
  694.  */
  695. {
  696.     int c, p;
  697.     double v[3], d;
  698.  
  699.     /* Parse packet */
  700.     if (2 != sscanf (pkt, "%*s %d %d", &c, &p))
  701.     {
  702.         Log ("ServerMDie: Malformed CRAT packet: %s", pkt);
  703.         return;
  704.     }
  705.  
  706.     /* Adjust frags */
  707.     client[c].frags--;
  708.  
  709.     /* Tell me about it */
  710.     Cprint ("%s cratered on %s",
  711.         target[client[c].target].name, planet[p].name);
  712.  
  713.     /* Was it me? */
  714.     if (c == clientme.client)
  715.     {
  716.         NetPlayerDies();
  717.     }
  718.     else
  719.     {
  720.         /* Make target hidden */
  721.         target[client[c].target].hidden = 1;
  722.  
  723.         /* Make a boom if close enough */
  724.         Vsub (v, player.pos, target[client[c].target].pos);
  725.         d = Mag2 (v);
  726.         if (d <= TARG_MAXRANGE2) Boom (target[client[c].target].pos, 1.0);
  727.     }
  728.  
  729.     CheckLock();
  730. }
  731.  
  732. ServerFire (pkt)
  733. char *pkt;
  734. /*
  735.  *  Someone nearby has fired a missile
  736.  */
  737. {
  738.     int c, t, w;
  739.  
  740.     /* Parse packet */
  741.     if (2 != sscanf (pkt, "%*s %d %d", &c, &w))
  742.     {
  743.         Log ("ServerFire: Malformed FIRE packet: %s", pkt);
  744.         return;
  745.     }
  746.  
  747.     /* Get target for this client */
  748.     t = client[c].target;
  749.  
  750.     /* Fire the missile! */
  751.     FireMissile (target[t].pos, target[t].vel, target[t].view,
  752.         0, w, t);
  753. }
  754.  
  755. ServerPlanet (pkt)
  756. char *pkt;
  757. /*
  758.  *  Server sends the position of a planet
  759.  */
  760. {
  761.     int p;
  762.     double theta;
  763.  
  764.     /* Parse packet */
  765.     if (2 != sscanf (pkt, "%*s %d %lf", &p, &theta))
  766.     {
  767.         Log ("ServerPlanet: Malformed PLAN packet: %s", pkt);
  768.         return;
  769.     }
  770.  
  771.     if ((p >= 0) && (p < NPLANETS)) planet[p].theta = theta;
  772. }
  773.  
  774. ServerBinaryPlanet (pkt)
  775. char *pkt;
  776. /*
  777.  *  Server sends the position of a planet in binary
  778.  */
  779. {
  780.     int p;
  781.     double theta;
  782.  
  783.     /* Parse packet */
  784.     DecodeBinaryPacket (pkt, "cF", &p, &theta);
  785.  
  786.     /* Set planet angle */
  787.     if ((p >= 0) && (p < NPLANETS)) planet[p].theta = theta;
  788. }
  789.  
  790. ServerResetPlanets (pkt)
  791. char *pkt;
  792. /*
  793.  *  Server done sending planet positions
  794.  */
  795. {
  796.     PositionPlanets();
  797. }
  798.  
  799. ServerName (pkt)
  800. char *pkt;
  801. /*
  802.  *  Server sends us the name of an active client
  803.  */
  804. {
  805.     int c, t, f;
  806.     char buf[256];
  807.  
  808.     /* Parse packet */
  809.     if (3 != sscanf (pkt, "%*s %d %s %d", &c, buf, &f))
  810.     {
  811.         Log ("ServerName: Malformed NAME packet: %s", pkt);
  812.         return;
  813.     }
  814.  
  815.     /* Sanity check */
  816.     if ((c<0) || (c>=NCLIENTS)) return;
  817.  
  818. /*    Log ("ServerName: NAME %d %s %d", c, buf, f);    */
  819.  
  820.     /* Don't bother if it's us */
  821.     if (c == clientme.client)
  822.     {
  823.         client[c].frags = f;
  824.         return;
  825.     }
  826.  
  827.     /* Show client is active */
  828.     client[c].active = 1;
  829.  
  830.     /* Set up a target if we didn't know about this one */
  831.     if ((-1) == (t = client[c].target))
  832.     {
  833.         t = InitClientTarget();
  834.         client[c].target = t;
  835.     }
  836.  
  837.     /* Set name and frags */
  838.     strcpy (target[t].name, buf);
  839.     client[c].frags = f;
  840. }
  841.  
  842. ServerHelo (pkt)
  843. char *pkt;
  844. /*
  845.  *  A new client has joined the game
  846.  */
  847. {
  848.     int c, t;
  849.     char buf[256];
  850.  
  851.     /* Parse packet */
  852.     if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
  853.     {
  854.         Log ("ServerName: Malformed HELO packet: %s", pkt);
  855.         return;
  856.     }
  857.  
  858.     /* Sanity check */
  859.     if ((c<0) || (c>=NCLIENTS)) return;
  860.  
  861.     /* Tell us */
  862.     Cprint ("%s is here", buf);
  863.     Log ("ServerHelo: HELO %d %s", c, buf);
  864.  
  865.     /* Don't bother if it's us */
  866.     if (c == clientme.client) return;
  867.  
  868.     /* Set up a target if we didn't know about this one */
  869.     if ((-1) == (t = client[c].target))
  870.     {
  871.         t = InitClientTarget();
  872.         client[c].target = t;
  873.     }
  874.  
  875.     /* Set name */
  876.     strcpy (target[t].name, buf);
  877. }
  878.  
  879. ServerVacant (pkt)
  880. char *pkt;
  881. /*
  882.  *  Server tells us about an unused client slot
  883.  */
  884. {
  885.     int c;
  886.  
  887.     /* Parse packet */
  888.     if (1 != sscanf (pkt, "%*s %d", &c))
  889.     {
  890.         Log ("ServerVacant: Malformed VCNT packet: %s", pkt);
  891.         return;
  892.     }
  893.  
  894.     if ((c<=0) || (c>=NCLIENTS)) return;
  895.  
  896.     Log ("ServerVacant: VCNT %d", c);
  897.  
  898.     /* Don't bother if it's us (this should never happen!) */
  899.     if (c == clientme.client)
  900.     {
  901.         Log ("ServerVacant: PANIC! Server says I am vacant!");
  902.         return;
  903.     }
  904.  
  905.     /* Destroy any associated target */
  906.     if ((-1) != client[c].target) DestroyTarget (client[c].target);
  907.     client[c].active = 0;
  908.     client[c].target = (-1);
  909. }
  910.  
  911. ServerGbye (pkt)
  912. char *pkt;
  913. /*
  914.  *  Someone has left the game
  915.  */
  916. {
  917.     int c;
  918.     char buf[256];
  919.  
  920.     /* Parse packet */
  921.     if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
  922.     {
  923.         Log ("ServerVacant: Malformed GBYE packet: %s", pkt);
  924.         return;
  925.     }
  926.  
  927.     if ((c<=0) || (c>=NCLIENTS)) return;
  928.  
  929.     Log ("ServerGbye: GBYE %d", c);
  930.  
  931.     /* Don't bother if it's us (this should never happen!) */
  932.     if (c == clientme.client)
  933.     {
  934.         Log ("ServerGbye: PANIC! Server says I am gone!");
  935.         return;
  936.     }
  937.  
  938.     /* Tell us */
  939.     Cprint ("%s is gone", buf);
  940.  
  941.     /* Destroy any associated target */
  942.     if ((-1) != client[c].target) DestroyTarget (client[c].target);
  943.     client[c].active = 0;
  944.     client[c].target = (-1);
  945. }
  946.  
  947. ServerCMSG (pkt)
  948. char *pkt;
  949. /*
  950.  *  Server has a console message for us
  951.  */
  952. {
  953.     /* Sanity */
  954.     if ( (pkt[4] == 0) || (pkt[5] == 0) ) return;
  955.  
  956.     /* Show it */
  957.     Cprint ("%s", &pkt[5]);
  958.  
  959.     /* Give the sound */
  960.     if (sound) PlayAudio (SOUND_COMM);
  961. }
  962.  
  963. ServerFlag (pkt)
  964. char *pkt;
  965. /*
  966.  *  Game flags from server
  967.  */
  968. {
  969.     int f;
  970.  
  971.     /* Parse packet */
  972.     if (1 != sscanf (pkt, "%*s %d", &f))
  973.     {
  974.         Log ("ServerFlag: Malformed FLAG packet: %s", pkt);
  975.         return;
  976.     }
  977.  
  978.     /* Set flags */
  979.     gravity = (f & FLAG_GRAVITY) ? 1 : 0;
  980.     player.flightmodel = (f & FLAG_FLIGHTMODEL) ? FLIGHT_ARCADE : FLIGHT_NEWTONIAN;
  981.     fullstop = (f & FLAG_FULLSTOP) ? 1 : 0;
  982.     realdistances = (f & FLAG_REALDISTANCES) ? 1 : 0;
  983.     orbit = (f & FLAG_ORBIT) ? 1 : 0;
  984. }
  985.  
  986. void DoConnect (void)
  987. /*
  988.  *  Sparky has finished typing the server address
  989.  */
  990. {
  991.     BecomeClient (text.buf);
  992. }
  993.  
  994. ServerModel (pkt)
  995. char *pkt;
  996. /*
  997.  *  Set client model
  998.  */
  999. {
  1000.     char buf[128];
  1001.     int m, c;
  1002.  
  1003.     /* Parse packet */
  1004.     if (2 != sscanf (pkt, "%*s %d %s", &c, buf))
  1005.     {
  1006.         Log ("ServerModel: Malformed MODL packet: %s", pkt);
  1007.         return;
  1008.     }
  1009.  
  1010.     /* Sanity */
  1011.     if ( (c < 0) || (c >= NCLIENTS) || (!client[c].active) || (client[c].is_me) ) return;
  1012.  
  1013.     /* Try to load model */
  1014.     m = LoadModel (buf);
  1015.  
  1016.     /* Success? */
  1017.     if (m != (-1))
  1018.     {
  1019.         target[client[c].target].model = m;
  1020.         target[client[c].target].list = model[m].list;
  1021.     }
  1022.     else
  1023.     {
  1024.         Log ("ServerModel: LoadModel (%s) failed", buf);
  1025.         /* Use default model */
  1026.         m = LoadModel ("light2.tri");
  1027.         target[client[c].target].model = m;
  1028.         target[client[c].target].list = model[m].list;
  1029.     }
  1030. }
  1031.  
  1032. ServerBinaryPacket (pkt)
  1033. unsigned char *pkt;
  1034. /*
  1035.  *  Handle binary packet from server
  1036.  */
  1037. {
  1038.     /* Dispatch */
  1039.     switch (pkt[0])
  1040.     {
  1041.     case PKT_POSS:
  1042.         BinaryPositionShort (&pkt[1]);
  1043.         break;
  1044.  
  1045.     case PKT_POSL:
  1046.         BinaryPositionLong (&pkt[1]);
  1047.         break;
  1048.  
  1049.     case PKT_PLAN:
  1050.         ServerBinaryPlanet (&pkt[1]);
  1051.         break;
  1052.  
  1053.     case PKT_VCNT:
  1054.         ServerBinaryVacant (&pkt[1]);
  1055.         break;
  1056.  
  1057.     case PKT_PING:
  1058.         ServerBinaryPing (&pkt[1]);
  1059.         break;
  1060.  
  1061.     default:
  1062.         Log ("ServerBinaryPacket: Unrecognized packet type: 0x%x",
  1063.             pkt[0]);
  1064.         break;
  1065.     }
  1066. }
  1067.  
  1068. BinaryPositionShort (pkt)
  1069. unsigned char *pkt;
  1070. /*
  1071.  *  Binary short position report
  1072.  */
  1073. {
  1074.     int c;
  1075.     double pos[3], vel[3];
  1076.  
  1077.     DecodeBinaryPacket (pkt, "cVV", &c, pos, vel);
  1078.     PositionShort (c, pos, vel);
  1079. }
  1080.  
  1081. BinaryPositionLong (pkt)
  1082. unsigned char *pkt;
  1083. /*
  1084.  *  Binary long position report
  1085.  */
  1086. {
  1087.     int c;
  1088.     double pos[3], vel[3], view[3], up[3];
  1089.     double move_up, move_down;
  1090.     double move_right, move_left, move_pitchright, move_pitchleft;
  1091.  
  1092.     DecodeBinaryPacket (pkt, "cVVvvffffff", &c, pos, vel, view, up,
  1093.         &move_up, &move_down, &move_right, &move_left,
  1094.         &move_pitchright, &move_pitchleft);
  1095.  
  1096.     PositionLong (c, pos, vel, view, up,
  1097.         move_up, move_down, move_right, move_left,
  1098.         move_pitchright, move_pitchleft);
  1099. }
  1100.  
  1101. ServerBinaryVacant (pkt)
  1102. char *pkt;
  1103. /*
  1104.  *  Server tells us which clients are in use
  1105.  */
  1106. {
  1107.     int c;
  1108.     unsigned int w, bit, i1, i2;
  1109.  
  1110.     /* Parse packet */
  1111.     DecodeBinaryPacket (pkt, "cc", &i1, &i2);
  1112.     w = i1 + 256*i2;
  1113.  
  1114.     /* See which bits are set */
  1115.     bit = 1;
  1116.  
  1117.     for (c=0; c<NCLIENTS; c++)
  1118.     {
  1119.         if (!(w & bit))
  1120.         {
  1121.             /* Don't bother if it's us (this should never happen!) */
  1122.             if (c == clientme.client)
  1123.             {
  1124.                 Log ("ServerVacant: PANIC! Server says I am vacant!");
  1125.                 return;
  1126.             }
  1127.  
  1128.             /* Destroy any associated target */
  1129.             if ((-1) != client[c].target) DestroyTarget (client[c].target);
  1130.             client[c].active = 0;
  1131.             client[c].target = (-1);
  1132.         }
  1133.  
  1134.         bit = bit * 2;
  1135.     }
  1136. }
  1137.  
  1138.