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