1 2 #define EXT_ACK -1 3 #define EXT_VERSION 105 4 #define EXT_NO_ERROR 0 5 #define EXT_ERROR 1 6 #define EXT_PLAYERSTATS_RESP_IDS -10 7 #define EXT_PLAYERSTATS_RESP_STATS -11 8 #define EXT_UPTIME 0 9 #define EXT_PLAYERSTATS 1 10 #define EXT_TEAMSCORE 2 11 12 /* 13 Client: 14 ----- 15 A: 0 EXT_UPTIME 16 B: 0 EXT_PLAYERSTATS cn #a client number or -1 for all players# 17 C: 0 EXT_TEAMSCORE 18 19 Server: 20 -------- 21 A: 0 EXT_UPTIME EXT_ACK EXT_VERSION uptime #in seconds# 22 B: 0 EXT_PLAYERSTATS cn #send by client# EXT_ACK EXT_VERSION 0 or 1 #error, if cn was > -1 and client does not exist# ... 23 EXT_PLAYERSTATS_RESP_IDS pid(s) #1 packet# 24 EXT_PLAYERSTATS_RESP_STATS pid playerdata #1 packet for each player# 25 C: 0 EXT_TEAMSCORE EXT_ACK EXT_VERSION 0 or 1 #error, no teammode# remaining_time gamemode loop(teamdata [numbases bases] or -1) 26 27 Errors: 28 -------------- 29 B:C:default: 0 command EXT_ACK EXT_VERSION EXT_ERROR 30 */ 31 extinfoplayer(ucharbuf & p,clientinfo * ci)32 void extinfoplayer(ucharbuf &p, clientinfo *ci) 33 { 34 ucharbuf q = p; 35 putint(q, EXT_PLAYERSTATS_RESP_STATS); // send player stats following 36 putint(q, ci->clientnum); //add player id 37 putint(q, ci->ping); 38 sendstring(ci->name, q); 39 sendstring(teamname(m_teammode ? ci->team : 0), q); 40 putint(q, ci->state.frags); 41 putint(q, ci->state.flags); 42 putint(q, ci->state.deaths); 43 putint(q, ci->state.teamkills); 44 putint(q, ci->state.damage*100/max(ci->state.shotdamage,1)); 45 putint(q, ci->state.health); 46 putint(q, 0); 47 putint(q, ci->state.gunselect); 48 putint(q, ci->privilege); 49 putint(q, ci->state.state); 50 uint ip = getclientip(ci->clientnum); 51 q.put((uchar*)&ip, 3); 52 sendserverinforeply(q); 53 } 54 extinfoteamscore(ucharbuf & p,int team,int score)55 static inline void extinfoteamscore(ucharbuf &p, int team, int score) 56 { 57 sendstring(teamname(team), p); 58 putint(p, score); 59 if(!smode || !smode->extinfoteam(team, p)) 60 putint(p,-1); //no bases follow 61 } 62 extinfoteams(ucharbuf & p)63 void extinfoteams(ucharbuf &p) 64 { 65 putint(p, m_teammode ? 0 : 1); 66 putint(p, gamemode); 67 putint(p, max((gamelimit - gamemillis)/1000, 0)); 68 if(!m_teammode) return; 69 70 vector<teamscore> scores; 71 if(smode && smode->hidefrags()) smode->getteamscores(scores); 72 loopv(clients) 73 { 74 clientinfo *ci = clients[i]; 75 if(ci->state.state!=CS_SPECTATOR && validteam(ci->team) && scores.htfind(ci->team) < 0) 76 { 77 if(smode && smode->hidefrags()) scores.add(teamscore(ci->team, 0)); 78 else { teaminfo &t = teaminfos[ci->team-1]; scores.add(teamscore(ci->team, t.frags)); } 79 } 80 } 81 loopv(scores) extinfoteamscore(p, scores[i].team, scores[i].score); 82 } 83 extserverinforeply(ucharbuf & req,ucharbuf & p)84 void extserverinforeply(ucharbuf &req, ucharbuf &p) 85 { 86 int extcmd = getint(req); // extended commands 87 88 //Build a new packet 89 putint(p, EXT_ACK); //send ack 90 putint(p, EXT_VERSION); //send version of extended info 91 92 switch(extcmd) 93 { 94 case EXT_UPTIME: 95 { 96 putint(p, totalsecs); //in seconds 97 break; 98 } 99 100 case EXT_PLAYERSTATS: 101 { 102 int cn = getint(req); //a special player, -1 for all 103 104 clientinfo *ci = NULL; 105 if(cn >= 0) 106 { 107 loopv(clients) if(clients[i]->clientnum == cn) { ci = clients[i]; break; } 108 if(!ci) 109 { 110 putint(p, EXT_ERROR); //client requested by id was not found 111 sendserverinforeply(p); 112 return; 113 } 114 } 115 116 putint(p, EXT_NO_ERROR); //so far no error can happen anymore 117 118 ucharbuf q = p; //remember buffer position 119 putint(q, EXT_PLAYERSTATS_RESP_IDS); //send player ids following 120 if(ci) putint(q, ci->clientnum); 121 else loopv(clients) putint(q, clients[i]->clientnum); 122 sendserverinforeply(q); 123 124 if(ci) extinfoplayer(p, ci); 125 else loopv(clients) extinfoplayer(p, clients[i]); 126 return; 127 } 128 129 case EXT_TEAMSCORE: 130 { 131 extinfoteams(p); 132 break; 133 } 134 135 default: 136 { 137 putint(p, EXT_ERROR); 138 break; 139 } 140 } 141 sendserverinforeply(p); 142 } 143 144