home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / clients2c.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-05  |  18.0 KB  |  620 lines

  1. // client processing of the incoming network stream
  2.  
  3. #include "cube.h"
  4. #include "bot/bot.h"
  5.  
  6. extern int democlientnum;
  7. extern bool c2sinit, senditemstoserver;
  8. extern string clientpassword;
  9.  
  10. void neterr(char *s)
  11. {
  12.     conoutf("\f3illegal network message (%s)", s);
  13.     disconnect();
  14. }
  15.  
  16. void changemapserv(char *name, int mode)        // forced map change from the server
  17. {
  18.     gamemode = mode;
  19.     load_world(name);
  20. }
  21.  
  22. void changemap(char *name)                      // request map change, server may ignore
  23. {
  24.     addmsg(SV_MAPCHANGE, "rsi", name, nextmode);
  25. }
  26.  
  27. // update the position of other clients in the game in our world
  28. // don't care if he's in the scenery or other players,
  29. // just don't overlap with our client
  30.  
  31. void updatepos(playerent *d)
  32. {
  33.     const float r = player1->radius+d->radius;
  34.     const float dx = player1->o.x-d->o.x;
  35.     const float dy = player1->o.y-d->o.y;
  36.     const float dz = player1->o.z-d->o.z;
  37.     const float rz = player1->aboveeye+d->eyeheight;
  38.     const float fx = (float)fabs(dx), fy = (float)fabs(dy), fz = (float)fabs(dz);
  39.     if(fx<r && fy<r && fz<rz && d->state!=CS_DEAD)
  40.     {
  41.         if(fx<fy) d->o.y += dy<0 ? r-fy : -(r-fy);  // push aside
  42.         else      d->o.x += dx<0 ? r-fx : -(r-fx);
  43.     }
  44. }
  45.  
  46. void updatelagtime(playerent *d)
  47. {
  48.     int lagtime = lastmillis-d->lastupdate;
  49.     if(lagtime)
  50.     {
  51.         d->plag = (d->plag*5+lagtime)/6;
  52.         d->lastupdate = lastmillis;
  53.     }
  54. }
  55.  
  56. extern void trydisconnect();
  57.  
  58. void parsepositions(ucharbuf &p)
  59. {
  60.     int type;
  61.     while(p.remaining()) switch(type = getint(p))
  62.     {
  63.         case SV_POS:                        // position of another client
  64.         {
  65.             int cn = getint(p);
  66.             vec o, vel;
  67.             float yaw, pitch, roll;
  68.             o.x   = getuint(p)/DMF;
  69.             o.y   = getuint(p)/DMF;
  70.             o.z   = getuint(p)/DMF;
  71.             yaw   = getuint(p)/DAF;
  72.             pitch = getint(p)/DAF;
  73.             roll  = getint(p)/DAF;
  74.             vel.x = getint(p)/DVF;
  75.             vel.y = getint(p)/DVF;
  76.             vel.z = getint(p)/DVF;
  77.             int f = getint(p);
  78.             playerent *d = getclient(cn);
  79.             if(!d) continue;
  80.             d->o = o;
  81.             d->yaw = yaw;
  82.             d->pitch = pitch;
  83.             d->roll = roll;
  84.             d->vel = vel;
  85.             d->strafe = (f&3)==3 ? -1 : f&3;
  86.             f >>= 2;  
  87.             d->move = (f&3)==3 ? -1 : f&3;
  88.             f >>= 2;
  89.             d->onfloor = f&1;
  90.             f >>= 1;
  91.             int oldstate = d->state, state = f&7; 
  92.             if(state==CS_DEAD && oldstate!=CS_DEAD) d->lastaction = lastmillis;
  93.             d->state = state; 
  94.             f >>= 3;
  95.             d->onladder = f&1;
  96.             if(!demoplayback) updatepos(d);
  97.             if(oldstate!=CS_DEAD && d->state!=CS_DEAD) updatelagtime(d);
  98.             break;
  99.         }
  100.  
  101.         default:
  102.             neterr("type");
  103.             return;
  104.     }
  105. }
  106.     
  107. void parsemessages(int cn, playerent *d, ucharbuf &p)
  108. {
  109.     static char text[MAXTRANS];
  110.     int type, joining = 0;
  111.     bool mapchanged = false, c2si = false, gib = false;
  112.  
  113.     while(p.remaining()) switch(type = getint(p))
  114.     {
  115.         case SV_INITS2C:                    // welcome messsage from the server
  116.         {
  117.             int mycn = getint(p), prot = getint(p);
  118.             if(prot!=PROTOCOL_VERSION)
  119.             {
  120.                 conoutf("you are using a different game protocol (you: %d, server: %d)", PROTOCOL_VERSION, prot);
  121.                 disconnect();
  122.                 return;
  123.             }
  124.             player1->clientnum = mycn;      // we are now fully connected
  125.             joining = getint(p);
  126.             if(getint(p) > 0) conoutf("INFO: this server is password protected");
  127.             if(joining<0 && getclientmap()[0]) changemap(getclientmap()); // we are the first client on this server, set map
  128.             break;
  129.         }
  130.  
  131.         case SV_CLIENT:
  132.         {
  133.             int cn = getint(p), len = getuint(p);
  134.             ucharbuf q = p.subbuf(len);
  135.             parsemessages(cn, getclient(cn), q);
  136.             break;
  137.         }
  138.  
  139.         case SV_SOUND:
  140.             playsound(getint(p), !d || localdemoplayer1st() ? NULL : &d->o);
  141.             break;
  142.         
  143.         
  144.         case SV_TEAMTEXT:
  145.         {
  146.             int cn = getint(p);
  147.             getstring(text, p);
  148.             filtertext(text, text);
  149.             playerent *d = getclient(cn);
  150.             if(!d) break;
  151.             conoutf("%s:\f1 %s", colorname(d), text);
  152.             break;
  153.         }
  154.  
  155.         case SV_TEXT:
  156.             if(cn == -1)
  157.             {
  158.                 getstring(text, p);
  159.                 conoutf("MOTD:");
  160.                 conoutf("\f4%s", text);
  161.             }
  162.             else if(d)
  163.             {
  164.                 getstring(text, p);
  165.                 filtertext(text, text);
  166.                 conoutf("%s:\f0 %s", colorname(d), text);
  167.             }
  168.             else return;
  169.             break;
  170.  
  171.         case SV_MAPCHANGE:     
  172.             getstring(text, p);
  173.             changemapserv(text, getint(p));
  174.             if(m_arena && joining>2)
  175.             {
  176.                 deathstate(player1);
  177.                 showscores(true);
  178.             }
  179.             mapchanged = true;
  180.             break;
  181.         
  182.         case SV_ITEMLIST:
  183.         {
  184.             int n;
  185.             if(mapchanged) { senditemstoserver = false; resetspawns(); }
  186.             while((n = getint(p))!=-1) if(mapchanged) setspawn(n, true);
  187.             break;
  188.         }
  189.  
  190.         case SV_MAPRELOAD:          // server requests next map
  191.         {
  192.             getint(p);
  193.             s_sprintfd(nextmapalias)("nextmap_%s", getclientmap());
  194.             char *map = getalias(nextmapalias);     // look up map in the cycle
  195.             changemap(map ? map : getclientmap());
  196.             break;
  197.         }
  198.  
  199.         case SV_INITC2S:            // another client either connected or changed name/team
  200.         {
  201.             d = newclient(cn);
  202.             getstring(text, p);
  203.             filtertext(text, text, false, MAXNAMELEN);
  204.             if(!text[0]) s_strcpy(text, "unarmed");
  205.             if(d->name[0])          // already connected
  206.             {
  207.                 if(strcmp(d->name, text))
  208.                     conoutf("%s is now known as %s", colorname(d, 0), colorname(d, 1, text));
  209.             }
  210.             else                    // new client
  211.             {
  212.                 c2sinit = false;    // send new players my info again 
  213.                 conoutf("connected: %s", colorname(d, 0, text));
  214.                 gun_changed = true;
  215.             } 
  216.             s_strncpy(d->name, text, MAXNAMELEN+1);
  217.             getstring(text, p);
  218.             filtertext(d->team, text, false, MAXTEAMLEN);
  219.             setskin(d, getint(p));
  220.             d->lifesequence = getint(p);
  221.             c2si = true;
  222.             if(m_ctf) loopi(2) 
  223.             {
  224.                 flaginfo &f = flaginfos[i];
  225.                 if(!f.actor) f.actor = getclient(f.actor_cn);
  226.             }
  227.             break;
  228.         }
  229.  
  230.         case SV_CDIS:
  231.         {
  232.             int cn = getint(p);
  233.             playerent *d = getclient(cn);
  234.             if(!d) break;
  235.             if(d->name[0]) conoutf("player %s disconnected", colorname(d)); 
  236.             zapplayer(players[cn]);
  237.             break;
  238.         }
  239.  
  240.         case SV_SHOT:
  241.         {
  242.             if(!d) return;
  243.             int gun = getint(p);
  244.             vec s, e;
  245.             s.x = getint(p)/DMF;
  246.             s.y = getint(p)/DMF;
  247.             s.z = getint(p)/DMF;
  248.             e.x = getint(p)/DMF;
  249.             e.y = getint(p)/DMF;
  250.             e.z = getint(p)/DMF;
  251.             if(gun==GUN_SHOTGUN) createrays(s, e);
  252.             d->lastaction = lastmillis;
  253.             d->lastattackgun = gun;
  254.             shootv(gun, s, e, d, false, getint(p));
  255.             break;
  256.         }
  257.         case SV_GIBDAMAGE:
  258.             gib = true;
  259.         case SV_DAMAGE:
  260.         {   
  261.             if(!d) return;
  262.             int target = getint(p);
  263.             int damage = getint(p);
  264.             int ls = getint(p);
  265.             if(target==getclientnum()) { if(ls==player1->lifesequence) dodamage(damage, cn, d, gib); }
  266.             else
  267.             {
  268.                 playerent *victim = getclient(target);
  269.                 if(victim)
  270.                 {
  271.                     playsound(S_PAIN1+rnd(5), &victim->o);
  272.                     victim->lastpain = lastmillis;
  273.                 }
  274.             }
  275.             gib = false;
  276.             break;
  277.         }
  278.         
  279.         case SV_GIBDIED:
  280.             gib = true;
  281.         case SV_DIED:
  282.         {
  283.             if(!d) return;
  284.             int actor = getint(p);
  285.             playerent *act = NULL;
  286.             s_sprintfd(death)("%s", gib ? "gibbed" : "fragged");
  287.  
  288.             if(actor==cn)
  289.             {
  290.                 conoutf("\f2%s suicided", colorname(d));
  291.                 act = d;
  292.             }
  293.             else if(actor==getclientnum() /*|| (demoplayback && actor==democlientnum)*/) // player-neutral gameplay messages?
  294.             {
  295.                 act = player1;
  296.                 int frags;
  297.                 if(isteam(player1->team, d->team))
  298.                 {
  299.                     frags = -1;
  300.                     conoutf("\f2you %s a teammate (%s)", death, colorname(d));
  301.                     extern void showteamkill();
  302.                     showteamkill();
  303.                 }
  304.                 else
  305.                 {
  306.                     frags = gib ? 2 : 1;
  307.                     conoutf("\f2you %s %s", death, colorname(d));
  308.                 }
  309.                 addmsg(SV_FRAGS, "ri", player1->frags += frags);
  310.                 if(gib) addgib(d);
  311.             }
  312.             else
  313.             {
  314.                 playerent *a = getclient(actor);
  315.                 if(a)
  316.                 {
  317.                     act = a;
  318.                     if(isteam(a->team, d->team))
  319.                     {
  320.                         conoutf("\f2%s %s his teammate (%s)", colorname(a, 0), death, colorname(d, 1));
  321.                     }
  322.                     else
  323.                     {
  324.                         conoutf("\f2%s %s %s", colorname(a, 0), death, colorname(d, 1));
  325.                     }
  326.                     if(gib) addgib(d);
  327.                 }
  328.             }
  329.             playsound(S_DIE1+rnd(2), &d->o);
  330.             if(act && act->gunselect == GUN_SNIPER && gib) playsound(S_HEADSHOT);
  331.             if(!c2si) d->lifesequence++;
  332.             gib = false;
  333.             break;
  334.         }
  335.         
  336.         case SV_FRAGS:
  337.             if(!d) return;
  338.             d->frags = getint(p);
  339.             break;
  340.  
  341.         case SV_RESUME:
  342.         {
  343.             int cn = getint(p), frags = getint(p), flags = getint(p), lseq = getint(p);
  344.             playerent *d = cn==getclientnum() ? player1 : newclient(cn);
  345.             if(d)
  346.             {
  347.                 d->frags = frags;
  348.                 d->flagscore = flags;
  349.                 d->lifesequence = lseq;
  350.             }
  351.             break;
  352.         }
  353.  
  354.         case SV_ITEMPICKUP:
  355.             setspawn(getint(p), false);
  356.             getint(p);
  357.             break;
  358.  
  359.         case SV_ITEMSPAWN:
  360.         {
  361.             uint i = getint(p);
  362.             setspawn(i, true);
  363.             break;
  364.         }
  365.  
  366.         case SV_ITEMACC:            // server acknowledges that I picked up this item
  367.             realpickup(getint(p), player1);
  368.             break;
  369.  
  370.         case SV_EDITH:              // coop editing messages, should be extended to include all possible editing ops
  371.         case SV_EDITT:
  372.         case SV_EDITS:
  373.         case SV_EDITD:
  374.         case SV_EDITE:
  375.         {
  376.             int x  = getint(p);
  377.             int y  = getint(p);
  378.             int xs = getint(p);
  379.             int ys = getint(p);
  380.             int v  = getint(p);
  381.             block b = { x, y, xs, ys };
  382.             switch(type)
  383.             {
  384.                 case SV_EDITH: editheightxy(v!=0, getint(p), b); break;
  385.                 case SV_EDITT: edittexxy(v, getint(p), b); break;
  386.                 case SV_EDITS: edittypexy(v, b); break;
  387.                 case SV_EDITD: setvdeltaxy(v, b); break;
  388.                 case SV_EDITE: editequalisexy(v!=0, b); break;
  389.             }
  390.             break;
  391.         }
  392.  
  393.         case SV_EDITENT:            // coop edit of ent
  394.         {
  395.             uint i = getint(p);
  396.             while((uint)ents.length()<=i) ents.add().type = NOTUSED;
  397.             int to = ents[i].type;
  398.             ents[i].type = getint(p);
  399.             ents[i].x = getint(p);
  400.             ents[i].y = getint(p);
  401.             ents[i].z = getint(p);
  402.             ents[i].attr1 = getint(p);
  403.             ents[i].attr2 = getint(p);
  404.             ents[i].attr3 = getint(p);
  405.             ents[i].attr4 = getint(p);
  406.             ents[i].spawned = false;
  407.             if(ents[i].type==LIGHT || to==LIGHT) calclight();
  408.             break;
  409.         }
  410.  
  411.         case SV_PONG: 
  412.             addmsg(SV_CLIENTPING, "i", player1->ping = (player1->ping*5+lastmillis-getint(p))/6);
  413.             break;
  414.  
  415.         case SV_CLIENTPING:
  416.             if(!d) return;
  417.             d->ping = getint(p);
  418.             break;
  419.  
  420.         case SV_GAMEMODE:
  421.             nextmode = getint(p);
  422.             break;
  423.  
  424.         case SV_TIMEUP:
  425.             timeupdate(getint(p));
  426.             break;
  427.  
  428.         case SV_RECVMAP:
  429.         {
  430.             getstring(text, p);
  431.             conoutf("received map \"%s\" from server, reloading..", &text);
  432.             int mapsize = getint(p);
  433.             if(p.remaining() < mapsize)
  434.             {
  435.                 p.forceoverread();
  436.                 break;
  437.             }
  438.             writemap(text, mapsize, &p.buf[p.len]);
  439.             p.len += mapsize;
  440.             changemapserv(text, gamemode);
  441.             break;
  442.         }
  443.         
  444.         case SV_WEAPCHANGE:
  445.         {
  446.             if(!d) return;
  447.             d->gunselect = getint(p);
  448.             break;
  449.         }
  450.         
  451.         case SV_SERVMSG:
  452.             getstring(text, p);
  453.             conoutf("%s", text);
  454.             break;
  455.  
  456.         case SV_FLAGINFO:
  457.         {
  458.             int flag = getint(p);
  459.             if(flag<0 || flag>1) return;
  460.             flaginfo &f = flaginfos[flag];
  461.             f.state = getint(p);
  462.             int action = getint(p);
  463.  
  464.             switch(f.state)
  465.             {
  466.                 case CTFF_STOLEN:
  467.                 { 
  468.                     flagstolen(flag, action, getint(p));
  469.                     break;
  470.                 }
  471.                 case CTFF_DROPPED:
  472.                 {
  473.                     short x = (ushort) (getint(p)/DMF);
  474.                     short y = (ushort) (getint(p)/DMF);
  475.                     short z = (ushort) (getint(p)/DMF);
  476.                     flagdropped(flag, action, x, y, z);
  477.                     break;
  478.                 }
  479.                 case CTFF_INBASE:
  480.                 {
  481.                     int actor = -1;
  482.                     if(action == SV_FLAGRETURN) actor = getint(p);
  483.                     flaginbase(flag, action, actor);
  484.                     break;
  485.                 }
  486.             }
  487.             break;
  488.         }
  489.         
  490.         case SV_FLAGS:
  491.         {
  492.             if(!d) return;
  493.             d->flagscore = getint(p);
  494.             break;
  495.         }
  496.  
  497.         case SV_ARENAWIN:
  498.         {
  499.             int alive = getint(p);
  500.             getstring(text, p);
  501.             conoutf("arena round is over! next round in 5 seconds...");
  502.             if(!alive) conoutf("everyone died!");
  503.             else if(m_botmode && player1->state==CS_DEAD) conoutf("the bots have won the round!");
  504.             else if(m_teammode) conoutf("team %s has won the round!", text);
  505.             else conoutf("%s is the survivor!", text);
  506.             break;
  507.         }
  508.  
  509.         case SV_ARENASPAWN:
  510.             conoutf("new round starting... fight!");
  511.             respawnself();
  512.             if(m_botmode) BotManager.RespawnBots();
  513.             clearbounceents();
  514.             break;
  515.  
  516.         case SV_SERVOPINFO:
  517.         {
  518.             loopv(players) { if(players[i]) players[i]->clientrole = CR_DEFAULT; }
  519.             player1->clientrole = CR_DEFAULT;
  520.  
  521.             int cl = getint(p), r = getint(p);
  522.             if(cl >= 0 && r >= 0)
  523.             {    
  524.                 playerent *pl = (cl == getclientnum() ? player1 : newclient(cl));
  525.                 if(pl)
  526.                 {
  527.                     pl->clientrole = r;
  528.                     if(pl->name[0]) conoutf("%s claimed %s status", pl == player1 ? "you" : colorname(pl), r == CR_ADMIN ? "admin" : "master");
  529.                 }
  530.             }
  531.             break;
  532.         }
  533.  
  534.         case SV_SERVOPCMD:
  535.         {
  536.             int cmd = getint(p), arg = getint(p);
  537.             playerent *pl = (arg == getclientnum() ? NULL : getclient(arg));
  538.             switch(cmd)
  539.             {
  540.                 case SOPCMD_KICK:
  541.                 case SOPCMD_BAN:
  542.                 {
  543.                     if(pl) conoutf("%s has been %s", colorname(pl), cmd == SOPCMD_KICK ? "kicked" : "banned");
  544.                     break;
  545.                 }
  546.                 case SOPCMD_REMBANS:
  547.                     conoutf("bans removed");
  548.                     break;
  549.                     
  550.                 case SOPCMD_MASTERMODE:
  551.                     conoutf("mastermode set to \"%s\"", arg ? "private" : "open");
  552.                     break;
  553.  
  554.                 case SOPCMD_AUTOTEAM:
  555.                     autoteambalance = arg == 1;
  556.                     if(!joining) conoutf("autoteam is %s", autoteambalance ? "enabled" : "disabled");
  557.                     break;
  558.  
  559.                 case SOPCMD_GIVEMASTER:
  560.                     if(pl) conoutf("the admin gave master state to %s", colorname(pl));
  561.                     break;
  562.  
  563.                 case SOPCMD_FORCETEAM:
  564.                     if(pl) conoutf("player %s was forced to change the team", colorname(pl));
  565.                     break;
  566.             }
  567.             break;
  568.         }
  569.  
  570.         case SV_SERVOPCMDDENIED:
  571.         {
  572.             conoutf("\f3denied. you have to be at least %s to perform this action", getint(p) == CR_ADMIN ? "admin" : "master");
  573.             break;
  574.         }
  575.  
  576.         case SV_FORCETEAM:
  577.         {
  578.             changeteam(getint(p));
  579.             if(!m_arena || joining<=2) spawnplayer(player1);
  580.             break;
  581.         }
  582.  
  583.         /* demo recording compat */
  584.         case SV_PING:
  585.             getint(p);
  586.             break;
  587.  
  588.         default:
  589.             if(demoplayback) // filter demo messages
  590.             {
  591.                 int size = msgsizelookup(type);
  592.                 if(size)
  593.                 {
  594.                     loopi(size) getint(p);
  595.                     break;
  596.                 }
  597.             }
  598.             neterr("type");
  599.             return;
  600.     }
  601. }
  602.  
  603. void localservertoclient(int chan, uchar *buf, int len)   // processes any updates from the server
  604. {
  605.     incomingdemodata(chan, buf, len);
  606.  
  607.     ucharbuf p(buf, len);
  608.  
  609.     switch(chan)
  610.     {
  611.         case 0: parsepositions(p); break;
  612.         case 1: 
  613.         case 2: parsemessages(-1, NULL, p); break;
  614.         case 42: // player1 demo data only
  615.             extern int democlientnum;
  616.             parsemessages(democlientnum, getclient(democlientnum), p);
  617.             break;
  618.     }
  619. }
  620.