summaryrefslogtreecommitdiff
path: root/src/fpsgame/extinfo.h
blob: b467a8c54b2a1548e54fec2f081344485b4f48a8 (plain) (blame)
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

#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);
		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;
		loopv(clients) {
			clientinfo *ci = clients[i];
			if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0) {
				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);
	}