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