1 /*
2 * Copyright (C) 2004 CreepLord (creeplord@pvpgn.org)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "common/setup_before.h"
20 #ifdef HAVE_STRING_H
21 # include <string.h>
22 #else
23 # ifdef HAVE_STRINGS_H
24 # include <strings.h>
25 # endif
26 # ifdef HAVE_MEMORY_H
27 # include <memory.h>
28 # endif
29 #endif
30 #ifdef STDC_HEADERS
31 # include <stdlib.h>
32 #else
33 # ifdef HAVE_MALLOC_H
34 # include <malloc.h>
35 # endif
36 #endif
37
38 #ifdef WIN32
39 # include "compat/socket.h" /* is this needed */
40 #endif
41
42 #include "compat/strdup.h"
43 #include "common/packet.h"
44 #include "common/eventlog.h"
45 #include "common/tag.h"
46 #include "team.h"
47 #include "account.h"
48 #include "account_wrap.h"
49 #include "connection.h"
50 #include "common/queue.h"
51 #include "prefs.h"
52 #include "common/bn_type.h"
53 #include "common/list.h"
54 #include "common/addr.h"
55 #include "common/xalloc.h"
56 #include "versioncheck.h"
57 #include "anongame.h"
58 #include "tournament.h"
59 #include "timer.h"
60 #include "ladder.h"
61 #include "server.h"
62 #include "anongame_maplists.h"
63 #include "anongame_gameresult.h"
64 #include "common/trans.h"
65 #include "common/setup_after.h"
66
67 #define MAX_LEVEL 100
68
69 /* [quetzal] 20020827 - this one get modified by anongame_queue player when there're enough
70 * players and map has been chosen based on their preferences. otherwise its NULL
71 */
72 static char *mapname = NULL;
73
74 static int players[ANONGAME_TYPES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
75 static t_connection *player[ANONGAME_TYPES][ANONGAME_MAX_GAMECOUNT];
76
77 /* [quetzal] 20020815 - queue to hold matching players */
78 static t_list *matchlists[ANONGAME_TYPES][MAX_LEVEL];
79
80 long average_anongame_search_time = 30;
81 unsigned int anongame_search_count = 0;
82
83 /**********************************************************************************/
84 static t_connection *_connlist_find_connection_by_uid(int uid);
85 static char const *_conn_get_versiontag(t_connection * c);
86
87 static int _anongame_gametype_to_queue(int type, int gametype);
88 static int _anongame_level_by_queue(t_connection * c, int queue);
89 static char *_get_map_from_prefs(int queue, t_uint32 cur_prefs, t_clienttag clienttag);
90 static unsigned int _anongame_get_gametype_tab(int queue);
91
92 static int _anongame_totalplayers(int queue);
93 static int _anongame_totalteams(int queue);
94
95 static int _handle_anongame_search(t_connection * c, t_packet const *packet);
96 static int _anongame_queue(t_connection * c, int queue, t_uint32 map_prefs);
97 static int _anongame_compare_level(void const *a, void const *b);
98 static int _anongame_order_queue(int queue);
99 static int _anongame_match(t_connection * c, int queue);
100 static int _anongame_search_found(int queue);
101 /**********************************************************************************/
102
_connlist_find_connection_by_uid(int uid)103 static t_connection *_connlist_find_connection_by_uid(int uid)
104 {
105 return connlist_find_connection_by_account(accountlist_find_account_by_uid(uid));
106 }
107
_conn_get_versiontag(t_connection * c)108 static char const *_conn_get_versiontag(t_connection * c)
109 {
110 return versioncheck_get_versiontag(conn_get_versioncheck(c));
111 }
112
113 /**********/
114
_anongame_queue_to_string(int queue)115 static char const *_anongame_queue_to_string(int queue)
116 {
117 switch (queue) {
118 case ANONGAME_TYPE_1V1:
119 return "PG 1v1";
120 case ANONGAME_TYPE_2V2:
121 return "PG 2v2";
122 case ANONGAME_TYPE_3V3:
123 return "PG 3v3";
124 case ANONGAME_TYPE_4V4:
125 return "PG 4v4";
126 case ANONGAME_TYPE_SMALL_FFA:
127 return "PG SFFA";
128 case ANONGAME_TYPE_AT_2V2:
129 return "AT 2v2";
130 case ANONGAME_TYPE_TEAM_FFA:
131 return "AT TFFA";
132 case ANONGAME_TYPE_AT_3V3:
133 return "AT 3v3";
134 case ANONGAME_TYPE_AT_4V4:
135 return "AT 4v4";
136 case ANONGAME_TYPE_TY:
137 return "TOURNEY";
138 case ANONGAME_TYPE_5V5:
139 return "PG 5v5";
140 case ANONGAME_TYPE_6V6:
141 return "PG 6v6";
142 case ANONGAME_TYPE_2V2V2:
143 return "PG 2v2v2";
144 case ANONGAME_TYPE_3V3V3:
145 return "PG 3v3v3";
146 case ANONGAME_TYPE_4V4V4:
147 return "PG 4v4v4";
148 case ANONGAME_TYPE_2V2V2V2:
149 return "PG 2v2v2v2";
150 case ANONGAME_TYPE_3V3V3V3:
151 return "PG 3v3v3v3";
152 case ANONGAME_TYPE_AT_2V2V2:
153 return "AT 2v2v2";
154 default:
155 eventlog(eventlog_level_error, __FUNCTION__, "invalid queue number %d", queue);
156 return "error";
157 }
158 }
159
_anongame_gametype_to_queue(int type,int gametype)160 static int _anongame_gametype_to_queue(int type, int gametype)
161 {
162 switch (type) {
163 case 0: /* PG */
164 switch (gametype) {
165 case 0:
166 return ANONGAME_TYPE_1V1;
167 case 1:
168 return ANONGAME_TYPE_2V2;
169 case 2:
170 return ANONGAME_TYPE_3V3;
171 case 3:
172 return ANONGAME_TYPE_4V4;
173 case 4:
174 return ANONGAME_TYPE_SMALL_FFA;
175 case 5:
176 return ANONGAME_TYPE_5V5;
177 case 6:
178 return ANONGAME_TYPE_6V6;
179 case 7:
180 return ANONGAME_TYPE_2V2V2;
181 case 8:
182 return ANONGAME_TYPE_3V3V3;
183 case 9:
184 return ANONGAME_TYPE_4V4V4;
185 case 10:
186 return ANONGAME_TYPE_2V2V2V2;
187 case 11:
188 return ANONGAME_TYPE_3V3V3V3;
189 default:
190 eventlog(eventlog_level_error, __FUNCTION__, "invalid PG game type: %d", gametype);
191 return -1;
192 }
193 case 1: /* AT */
194 switch (gametype) {
195 case 0:
196 return ANONGAME_TYPE_AT_2V2;
197 case 2:
198 return ANONGAME_TYPE_AT_3V3;
199 case 3:
200 return ANONGAME_TYPE_AT_4V4;
201 case 4:
202 return ANONGAME_TYPE_AT_2V2V2;
203 default:
204 eventlog(eventlog_level_error, __FUNCTION__, "invalid AT game type: %d", gametype);
205 return -1;
206 }
207 case 2: /* TY */
208 return ANONGAME_TYPE_TY;
209 default:
210 eventlog(eventlog_level_error, __FUNCTION__, "invalid type: %d", type);
211 return -1;
212 }
213 }
214
_anongame_level_by_queue(t_connection * c,int queue)215 static int _anongame_level_by_queue(t_connection * c, int queue)
216 {
217 t_clienttag ct = conn_get_clienttag(c);
218
219 switch (queue) {
220 case ANONGAME_TYPE_1V1:
221 return account_get_ladder_level(conn_get_account(c), ct, ladder_id_solo);
222 case ANONGAME_TYPE_2V2:
223 case ANONGAME_TYPE_3V3:
224 case ANONGAME_TYPE_4V4:
225 case ANONGAME_TYPE_5V5:
226 case ANONGAME_TYPE_6V6:
227 case ANONGAME_TYPE_2V2V2:
228 case ANONGAME_TYPE_3V3V3:
229 case ANONGAME_TYPE_4V4V4:
230 case ANONGAME_TYPE_2V2V2V2:
231 case ANONGAME_TYPE_3V3V3V3:
232 return account_get_ladder_level(conn_get_account(c), ct, ladder_id_ffa);
233 case ANONGAME_TYPE_SMALL_FFA:
234 case ANONGAME_TYPE_TEAM_FFA:
235 return account_get_ladder_level(conn_get_account(c), ct, ladder_id_ffa);
236 case ANONGAME_TYPE_AT_2V2:
237 case ANONGAME_TYPE_AT_3V3:
238 case ANONGAME_TYPE_AT_4V4:
239 case ANONGAME_TYPE_AT_2V2V2:
240 return 0;
241 case ANONGAME_TYPE_TY: /* set to ((wins * 3) + ties - losses) ie. prelim score */
242 return tournament_get_player_score(conn_get_account(c));
243 default:
244 eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue);
245 return -1;
246 }
247 }
248
_get_map_from_prefs(int queue,t_uint32 cur_prefs,t_clienttag clienttag)249 static char *_get_map_from_prefs(int queue, t_uint32 cur_prefs, t_clienttag clienttag)
250 {
251 int i, j = 0;
252 char *default_map, *selected;
253 char *res_maps[32];
254 char clienttag_str[5];
255
256 if (clienttag == CLIENTTAG_WARCRAFT3_UINT)
257 default_map = "Maps\\(8)PlainsOfSnow.w3m";
258 else if (clienttag == CLIENTTAG_WAR3XP_UINT)
259 default_map = "Maps\\(8)PlainsOfSnow.w3m";
260 else {
261 eventlog(eventlog_level_error, __FUNCTION__, "invalid clienttag : %s", tag_uint_to_str(clienttag_str,clienttag));
262 return "Maps\\(8)PlainsOfSnow.w3m";
263 }
264
265 for (i = 0; i < 32; i++)
266 res_maps[i] = NULL;
267
268 for (i = 0; i < 32; i++) {
269 if (cur_prefs & 1)
270 res_maps[j++] = maplists_get_map(queue, clienttag, i + 1);
271 cur_prefs >>= 1;
272 }
273
274 i = rand() % j;
275 if (res_maps[i])
276 selected = res_maps[i];
277 else
278 selected = default_map;
279
280 eventlog(eventlog_level_trace, __FUNCTION__, "got map %s from prefs", selected);
281 return selected;
282 }
283
_anongame_get_gametype_tab(int queue)284 static unsigned int _anongame_get_gametype_tab(int queue)
285 {
286 /* dizzy: this changed in 1.05 */
287 switch (queue) {
288 case ANONGAME_TYPE_1V1:
289 return SERVER_ANONGAME_SOLO_STR;
290 case ANONGAME_TYPE_2V2:
291 case ANONGAME_TYPE_3V3:
292 case ANONGAME_TYPE_4V4:
293 case ANONGAME_TYPE_5V5:
294 case ANONGAME_TYPE_6V6:
295 case ANONGAME_TYPE_2V2V2:
296 case ANONGAME_TYPE_3V3V3:
297 case ANONGAME_TYPE_4V4V4:
298 case ANONGAME_TYPE_2V2V2V2:
299 case ANONGAME_TYPE_3V3V3V3:
300 return SERVER_ANONGAME_TEAM_STR;
301 case ANONGAME_TYPE_SMALL_FFA:
302 return SERVER_ANONGAME_SFFA_STR;
303 case ANONGAME_TYPE_TEAM_FFA:
304 return 0; /* Team FFA is no longer supported */
305 case ANONGAME_TYPE_AT_2V2:
306 return SERVER_ANONGAME_AT2v2_STR;
307 case ANONGAME_TYPE_AT_3V3:
308 return SERVER_ANONGAME_AT3v3_STR;
309 case ANONGAME_TYPE_AT_4V4:
310 return SERVER_ANONGAME_AT4v4_STR;
311 case ANONGAME_TYPE_AT_2V2V2:
312 return SERVER_ANONGAME_AT2v2_STR; /* fixme */
313 case ANONGAME_TYPE_TY:
314 return SERVER_ANONGAME_TY_STR;
315 default:
316 eventlog(eventlog_level_error, __FUNCTION__, "invalid queue (%d)", queue);
317 return 0;
318 }
319 }
320
_anongame_totalplayers(int queue)321 static int _anongame_totalplayers(int queue)
322 {
323 switch (queue) {
324 case ANONGAME_TYPE_1V1:
325 return 2;
326 case ANONGAME_TYPE_2V2:
327 case ANONGAME_TYPE_AT_2V2:
328 case ANONGAME_TYPE_SMALL_FFA: /* fixme: total players not always 4 */
329 return 4;
330 case ANONGAME_TYPE_3V3:
331 case ANONGAME_TYPE_AT_3V3:
332 case ANONGAME_TYPE_2V2V2:
333 case ANONGAME_TYPE_AT_2V2V2:
334 return 6;
335 case ANONGAME_TYPE_4V4:
336 case ANONGAME_TYPE_AT_4V4:
337 case ANONGAME_TYPE_TEAM_FFA:
338 case ANONGAME_TYPE_2V2V2V2:
339 return 8;
340 case ANONGAME_TYPE_3V3V3:
341 return 9;
342 case ANONGAME_TYPE_5V5:
343 return 10;
344 case ANONGAME_TYPE_6V6:
345 case ANONGAME_TYPE_4V4V4:
346 case ANONGAME_TYPE_3V3V3V3:
347 return 12;
348 case ANONGAME_TYPE_TY:
349 return tournament_get_totalplayers();
350 default:
351 eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue);
352 return 0;
353 }
354 }
355
_anongame_totalteams(int queue)356 static int _anongame_totalteams(int queue)
357 {
358 /* dont forget to change this if you make some game type with more teams */
359 #define ANONGAME_MAX_TEAMS 4
360 switch (queue) {
361 case ANONGAME_TYPE_1V1:
362 case ANONGAME_TYPE_SMALL_FFA:
363 return 0;
364 case ANONGAME_TYPE_2V2:
365 case ANONGAME_TYPE_3V3:
366 case ANONGAME_TYPE_4V4:
367 case ANONGAME_TYPE_5V5:
368 case ANONGAME_TYPE_6V6:
369 case ANONGAME_TYPE_AT_2V2:
370 case ANONGAME_TYPE_AT_3V3:
371 case ANONGAME_TYPE_AT_4V4:
372 return 2;
373 case ANONGAME_TYPE_2V2V2:
374 case ANONGAME_TYPE_3V3V3:
375 case ANONGAME_TYPE_4V4V4:
376 case ANONGAME_TYPE_AT_2V2V2:
377 return 3;
378 case ANONGAME_TYPE_TEAM_FFA: /* not even used */
379 case ANONGAME_TYPE_2V2V2V2:
380 case ANONGAME_TYPE_3V3V3V3:
381 return 4;
382 case ANONGAME_TYPE_TY:
383 return 2; /* fixme: does not support 2v2v2 - tournament_get_totalteams() */
384 default:
385 eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue);
386 return 0;
387 }
388 }
389
390 /**********/
_handle_anongame_search(t_connection * c,t_packet const * packet)391 static int _handle_anongame_search(t_connection * c, t_packet const *packet)
392 {
393 int i, j, temp, set = 1;
394 t_packet *rpacket;
395 t_connection *tc[6];
396 t_anongame *a, *ta;
397 t_uint8 teamsize = 0;
398 t_uint8 option = bn_byte_get(packet->u.client_findanongame.option);
399
400 if (!(a = conn_get_anongame(c))) {
401 if (!(a = conn_create_anongame(c))) {
402 eventlog(eventlog_level_error, __FUNCTION__, "[%d] conn_create_anongame failed", conn_get_socket(c));
403 return -1;
404 }
405 }
406
407 conn_set_anongame_search_starttime(c, now);
408
409 switch (option) {
410 case CLIENT_FINDANONGAME_AT_INVITER_SEARCH:
411 a->count = bn_int_get(packet->u.client_findanongame_at_inv.count);
412 a->id = bn_int_get(packet->u.client_findanongame_at_inv.id);
413 a->tid = bn_int_get(packet->u.client_findanongame_at_inv.tid);
414 a->race = bn_int_get(packet->u.client_findanongame_at_inv.race);
415 a->map_prefs = bn_int_get(packet->u.client_findanongame_at_inv.map_prefs);
416 a->type = bn_byte_get(packet->u.client_findanongame_at_inv.type);
417 a->gametype = bn_byte_get(packet->u.client_findanongame_at_inv.gametype);
418 teamsize = bn_byte_get(packet->u.client_findanongame_at_inv.teamsize);
419 break;
420 case CLIENT_FINDANONGAME_AT_SEARCH:
421 a->count = bn_int_get(packet->u.client_findanongame_at.count);
422 a->id = bn_int_get(packet->u.client_findanongame_at.id);
423 a->tid = bn_int_get(packet->u.client_findanongame_at.tid);
424 a->race = bn_int_get(packet->u.client_findanongame_at.race);
425 teamsize = bn_byte_get(packet->u.client_findanongame_at.teamsize);
426 break;
427 case CLIENT_FINDANONGAME_SEARCH:
428 a->count = bn_int_get(packet->u.client_findanongame.count);
429 a->id = bn_int_get(packet->u.client_findanongame.id);
430 a->race = bn_int_get(packet->u.client_findanongame.race);
431 a->map_prefs = bn_int_get(packet->u.client_findanongame.map_prefs);
432 a->type = bn_byte_get(packet->u.client_findanongame.type);
433 a->gametype = bn_byte_get(packet->u.client_findanongame.gametype);
434 break;
435 default:
436 eventlog(eventlog_level_error, __FUNCTION__, "invalid search option (%d)", option);
437 return -1;
438 }
439
440 if (option != CLIENT_FINDANONGAME_AT_SEARCH)
441 if ((a->queue = _anongame_gametype_to_queue(a->type, a->gametype)) < 0) {
442 eventlog(eventlog_level_error, __FUNCTION__, "invalid queue: %d", a->queue);
443 return -1;
444 }
445
446 account_set_w3pgrace(conn_get_account(c), conn_get_clienttag(c), a->race);
447
448 /* send search reply to client */
449 if (!(rpacket = packet_create(packet_class_bnet)))
450 return -1;
451 packet_set_size(rpacket, sizeof(t_server_anongame_search_reply));
452 packet_set_type(rpacket, SERVER_ANONGAME_SEARCH_REPLY);
453 bn_byte_set(&rpacket->u.server_anongame_search_reply.option, SERVER_FINDANONGAME_SEARCH);
454 bn_int_set(&rpacket->u.server_anongame_search_reply.count, a->count);
455 bn_int_set(&rpacket->u.server_anongame_search_reply.reply, 0);
456 temp = (int) average_anongame_search_time;
457 packet_append_data(rpacket, &temp, 2);
458 conn_push_outqueue(c, rpacket);
459 packet_del_ref(rpacket);
460 /* end search reply */
461
462 switch (option) {
463 case CLIENT_FINDANONGAME_AT_INVITER_SEARCH:
464 for (i = 0; i < teamsize; i++) { /* assign player conns to tc[] array */
465 if (!(tc[i] = _connlist_find_connection_by_uid(bn_int_get(packet->u.client_findanongame_at_inv.info[i])))) {
466 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(tc[i]));
467 return -1;
468 }
469 }
470 for (i = 0; i < teamsize; i++) { /* assign info from inviter to other team players */
471 if (!(ta = conn_get_anongame(tc[i]))) {
472 if (!(ta = conn_create_anongame(tc[i]))) {
473 eventlog(eventlog_level_error, __FUNCTION__, "[%d] conn_create_anongame failed", conn_get_socket(tc[i]));
474 return -1;
475 }
476 }
477 for (j = 0; j < teamsize; j++) /* add each players conn to each anongame struct */
478 ta->tc[j] = tc[j];
479
480 ta->type = a->type;
481 ta->gametype = a->gametype;
482 ta->queue = a->queue;
483 ta->map_prefs = a->map_prefs;
484
485 if (ta->tid != a->tid)
486 set = 0;
487 }
488 if (!set) /* check if search packet has been recieved from each team member */
489 return 0;
490 break;
491 case CLIENT_FINDANONGAME_AT_SEARCH:
492 for (i = 0; i < teamsize; i++) { /* assign player conns to tc[] array */
493 if (!(tc[i] = _connlist_find_connection_by_uid(bn_int_get(packet->u.client_findanongame_at.info[i])))) {
494 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(tc[i]));
495 return -1;
496 }
497 }
498 for (i = 0; i < teamsize; i++) { /* check if search packet has been recieved from each team member */
499 if (!(ta = conn_get_anongame(tc[i])))
500 return 0;
501 if (ta->tid != a->tid)
502 return 0;
503 }
504 break;
505 case CLIENT_FINDANONGAME_SEARCH:
506 tc[0] = c;
507 a->tc[0] = c;
508 break;
509 default:
510 eventlog(eventlog_level_error, __FUNCTION__, "invalid search option (%d)", option);
511 return -1;
512 }
513
514 if (_anongame_queue(tc[0], a->queue, a->map_prefs) < 0) {
515 eventlog(eventlog_level_error, __FUNCTION__, "queue failed");
516 return -1;
517 }
518
519 _anongame_match(c, a->queue);
520
521 /* if enough players are queued send found packet */
522 if (players[a->queue] == _anongame_totalplayers(a->queue))
523 if (_anongame_search_found(a->queue) < 0)
524 return -1;
525
526 return 0;
527 }
528
_anongame_queue(t_connection * c,int queue,t_uint32 map_prefs)529 static int _anongame_queue(t_connection * c, int queue, t_uint32 map_prefs)
530 {
531 int level;
532 t_matchdata *md;
533
534 if (!c) {
535 eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
536 }
537
538 if (queue >= ANONGAME_TYPES) {
539 eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue);
540 return -1;
541 }
542
543 level = _anongame_level_by_queue(c, queue);
544
545 if (!matchlists[queue][level])
546 matchlists[queue][level] = list_create();
547
548 md = xmalloc(sizeof(t_matchdata));
549 md->c = c;
550 md->map_prefs = map_prefs;
551 md->versiontag = _conn_get_versiontag(c);
552
553 list_append_data(matchlists[queue][level], md);
554
555 return 0;
556 }
557
_anongame_compare_level(void const * a,void const * b)558 static int _anongame_compare_level(void const *a, void const *b)
559 {
560 t_connection *ca = *(t_connection * const *) a;
561 t_connection *cb = *(t_connection * const *) b;
562
563 int level_a = _anongame_level_by_queue(ca, anongame_get_queue(conn_get_anongame(ca)));
564 int level_b = _anongame_level_by_queue(cb, anongame_get_queue(conn_get_anongame(cb)));
565
566 return (level_a > level_b) ? -1 : ((level_a < level_b) ? 1 : 0);
567 }
568
_anongame_order_queue(int queue)569 static int _anongame_order_queue(int queue)
570 {
571 if (_anongame_totalteams(queue) != 0 && !anongame_arranged(queue)) { /* no need to reorder 1v1, sffa, or AT queues */
572 int i, j;
573 t_connection *temp;
574 int level[ANONGAME_MAX_TEAMS];
575 int teams = _anongame_totalteams(queue); /* number of teams */
576 int ppt = players[queue] / teams; /* players per team */
577
578 for (i = 0; i < ANONGAME_MAX_TEAMS; i++)
579 level[i] = 0;
580
581 for (i = 0; i < ppt - 1; i++) { /* loop through the number of players per team */
582 for (j = 0; j < teams; j++) {
583 level[j] = level[j] + _anongame_level_by_queue(player[queue][i * ppt + j], queue);
584 }
585
586 if (teams == 2) {
587 /* 1 >= 2 */
588 if (level[i * teams] >= level[i * teams + 1]) {
589 temp = player[queue][(i + 1) * teams];
590 player[queue][(i + 1) * teams] = player[queue][(i + 1) * teams + 1];
591 player[queue][(i + 1) * teams + 1] = temp;
592 }
593 /* 2 >= 1 */
594 else if (level[i * teams + 1] >= level[i * teams]) {
595 ; /* nothing to do */
596 }
597 }
598 /* end 2 teams */
599 else if (teams == 3) {
600 /* 1 >= 2 >= 3 */
601 if (level[i * 3] >= level[i * 3 + 1] && level[i * 3 + 1] >= level[i * 3 + 2]) {
602 temp = player[queue][(i + 1) * 3];
603 player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 2];
604 player[queue][(i + 1) * 3 + 2] = temp;
605 }
606 /* 1 >= 3 >= 2 */
607 else if (level[i * 3] >= level[i * 3 + 2] && level[i * 3 + 2] >= level[i * 3 + 1]) {
608 temp = player[queue][(i + 1) * 3];
609 player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 2];
610 player[queue][(i + 1) * 3 + 2] = player[queue][(i + 1) * 3 + 1];
611 player[queue][(i + 1) * 3 + 1] = temp;
612 }
613 /* 2 >= 1 >= 3 */
614 else if (level[i * 3 + 1] >= level[i * 3] && level[i * 3] >= level[i * 3 + 2]) {
615 temp = player[queue][(i + 1) * 3];
616 player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 1];
617 player[queue][(i + 1) * 3 + 1] = player[queue][(i + 1) * 3 + 2];
618 player[queue][(i + 1) * 3 + 2] = temp;
619 }
620 /* 2 >= 3 >= 1 */
621 else if (level[i * 3 + 1] >= level[i * 3 + 2] && level[i * 3 + 2] >= level[i * 3]) {
622 temp = player[queue][(i + 1) * 3 + 1];
623 player[queue][(i + 1) * 3 + 1] = player[queue][(i + 1) * 3 + 2];
624 player[queue][(i + 1) * 3 + 2] = temp;
625 }
626 /* 3 >= 1 >= 2 */
627 else if (level[i * 3 + 2] >= level[i * 3] && level[i * 3] >= level[i * 3 + 1]) {
628 temp = player[queue][(i + 1) * 3];
629 player[queue][(i + 1) * 3] = player[queue][(i + 1) * 3 + 1];
630 player[queue][(i + 1) * 3 + 1] = temp;
631 }
632 /* 3 >= 2 >= 1 */
633 else if (level[i * 3 + 2] >= level[i * 3 + 1] && level[i * 3 + 1] >= level[i * 3]) {
634 ; /* nothing to do */
635 }
636 }
637 /* end 3 teams */
638 else if (teams == 4) {
639 /* 1234 */
640 if (level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3]) {
641 temp = player[queue][(i + 1) * 4];
642 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
643 player[queue][(i + 1) * 4 + 3] = temp;
644 temp = player[queue][(i + 1) * 4 + 1];
645 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
646 player[queue][(i + 1) * 4 + 2] = temp;
647 }
648 /* 1243 */
649 else if (level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 3] >= level[i * 4 + 2]) {
650 temp = player[queue][(i + 1) * 4];
651 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
652 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1];
653 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
654 player[queue][(i + 1) * 4 + 2] = temp;
655 }
656 /* 1324 */
657 else if (level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 3]) {
658 temp = player[queue][(i + 1) * 4];
659 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
660 player[queue][(i + 1) * 4 + 3] = temp;
661 }
662 /* 1342 */
663 else if (level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1]) {
664 temp = player[queue][(i + 1) * 4];
665 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
666 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1];
667 player[queue][(i + 1) * 4 + 1] = temp;
668 }
669 /* 1423 */
670 else if (level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2]) {
671 temp = player[queue][(i + 1) * 4];
672 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
673 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2];
674 player[queue][(i + 1) * 4 + 2] = temp;
675 }
676 /* 1432 */
677 else if (level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1]) {
678 temp = player[queue][(i + 1) * 4];
679 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
680 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2];
681 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 1];
682 player[queue][(i + 1) * 4 + 1] = temp;
683 }
684 /* 2134 */
685 else if (level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3]) {
686 temp = player[queue][(i + 1) * 4];
687 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2];
688 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 1];
689 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3];
690 player[queue][(i + 1) * 4 + 3] = temp;
691 }
692 /* 2143 */
693 else if (level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 2]) {
694 temp = player[queue][(i + 1) * 4];
695 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2];
696 player[queue][(i + 1) * 4 + 2] = temp;
697 temp = player[queue][(i + 1) * 4 + 1];
698 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3];
699 player[queue][(i + 1) * 4 + 3] = temp;
700 }
701 /* 2314 */
702 else if (level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3]) {
703 temp = player[queue][(i + 1) * 4];
704 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 3];
705 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1];
706 player[queue][(i + 1) * 4 + 1] = temp;
707 }
708 /* 2341 */
709 else if (level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4]) {
710 temp = player[queue][(i + 1) * 4 + 1];
711 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
712 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
713 player[queue][(i + 1) * 4 + 3] = temp;
714 }
715 /* 2413 */
716 else if (level[i * 4 + 1] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2]) {
717 temp = player[queue][(i + 1) * 4];
718 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1];
719 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3];
720 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2];
721 player[queue][(i + 1) * 4 + 2] = temp;
722 }
723 /* 2431 */
724 else if (level[i * 4 + 1] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4]) {
725 temp = player[queue][(i + 1) * 4 + 1];
726 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 3];
727 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 2];
728 player[queue][(i + 1) * 4 + 2] = temp;
729 }
730 /* 3124 */
731 else if (level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 3]) {
732 temp = player[queue][(i + 1) * 4];
733 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2];
734 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
735 player[queue][(i + 1) * 4 + 3] = temp;
736 }
737 /* 3142 */
738 else if (level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1]) {
739 temp = player[queue][(i + 1) * 4];
740 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2];
741 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
742 player[queue][(i + 1) * 4 + 3] = player[queue][(i + 1) * 4 + 1];
743 player[queue][(i + 1) * 4 + 1] = temp;
744 }
745 /* 3214 */
746 else if (level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 3]) {
747 temp = player[queue][(i + 1) * 4];
748 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1];
749 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
750 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
751 player[queue][(i + 1) * 4 + 3] = temp;
752 }
753 /* 3241 */
754 else if (level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4]) {
755 temp = player[queue][(i + 1) * 4 + 1];
756 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
757 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
758 player[queue][(i + 1) * 4 + 3] = temp;
759 }
760 /* 3412 */
761 else if (level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1]) {
762 temp = player[queue][(i + 1) * 4];
763 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1];
764 player[queue][(i + 1) * 4 + 1] = temp;
765 temp = player[queue][(i + 1) * 4 + 2];
766 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
767 player[queue][(i + 1) * 4 + 3] = temp;
768 }
769 /* 3421 */
770 else if (level[i * 4 + 2] >= level[i * 4 + 3] && level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4]) {
771 temp = player[queue][(i + 1) * 4 + 2];
772 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 3];
773 player[queue][(i + 1) * 4 + 3] = temp;
774 }
775 /* 4123 */
776 else if (level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2]) {
777 temp = player[queue][(i + 1) * 4];
778 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2];
779 player[queue][(i + 1) * 4 + 2] = temp;
780 }
781 /* 4132 */
782 else if (level[i * 4 + 3] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1]) {
783 temp = player[queue][(i + 1) * 4];
784 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 2];
785 player[queue][(i + 1) * 4 + 2] = player[queue][(i + 1) * 4 + 1];
786 player[queue][(i + 1) * 4 + 1] = temp;
787 }
788 /* 4213 */
789 else if (level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4] && level[i * 4] >= level[i * 4 + 2]) {
790 temp = player[queue][(i + 1) * 4];
791 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1];
792 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
793 player[queue][(i + 1) * 4 + 2] = temp;
794 }
795 /* 4231 */
796 else if (level[i * 4 + 3] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4]) {
797 temp = player[queue][(i + 1) * 4 + 1];
798 player[queue][(i + 1) * 4 + 1] = player[queue][(i + 1) * 4 + 2];
799 player[queue][(i + 1) * 4 + 2] = temp;
800 }
801 /* 4312 */
802 else if (level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4] && level[i * 4] >= level[i * 4 + 1]) {
803 temp = player[queue][(i + 1) * 4];
804 player[queue][(i + 1) * 4] = player[queue][(i + 1) * 4 + 1];
805 player[queue][(i + 1) * 4 + 1] = temp;
806 }
807 /* 4321 */
808 else if (level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4]) {
809 ; /* nothing to do */
810 }
811 } /* end 4 teams */
812 } /* end ppt loop */
813 } /* end "if" statement */
814 return 0;
815 }
816
_anongame_match(t_connection * c,int queue)817 static int _anongame_match(t_connection * c, int queue)
818 {
819 int level = _anongame_level_by_queue(c, queue);
820 int delta = 0;
821 int i;
822 t_matchdata *md;
823 t_elem *curr;
824 int diff;
825 t_anongame *a = conn_get_anongame(c);
826 t_uint32 cur_prefs = a->map_prefs;
827 t_connection *inv_c[ANONGAME_MAX_TEAMS];
828 int maxlevel, minlevel;
829 int teams = 0;
830 players[queue] = 0;
831
832 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] matching started for level %d player in queue %d", conn_get_socket(c), level, queue);
833
834 diff = war3_get_maxleveldiff();
835 maxlevel = level + diff;
836 minlevel = (level - diff < 0) ? 0 : level - diff;
837
838 while (abs(delta) < (diff + 1)) {
839 if ((level + delta <= maxlevel) && (level + delta >= minlevel)) {
840 eventlog(eventlog_level_trace, __FUNCTION__, "Traversing level %d players", level + delta);
841
842 LIST_TRAVERSE(matchlists[queue][level + delta], curr) {
843 md = elem_get_data(curr);
844 if (md->versiontag && _conn_get_versiontag(c) && !strcmp(md->versiontag, _conn_get_versiontag(c)) && (cur_prefs & md->map_prefs)) {
845 /* set maxlevel and minlevel to keep all players within 6 levels */
846 maxlevel = (level + delta + diff < maxlevel) ? level + delta + diff : maxlevel;
847 minlevel = (level + delta - diff > minlevel) ? level + delta - diff : minlevel;
848 cur_prefs &= md->map_prefs;
849
850 /* AT match */
851 if (anongame_arranged(queue)) {
852
853 /* set the inv_c for unqueueing later */
854 inv_c[teams] = md->c;
855
856 a = conn_get_anongame(md->c);
857
858 /* add all the players on the team to player[][] */
859 for (i = 0; i < _anongame_totalplayers(queue) / _anongame_totalteams(queue); i++) {
860 player[queue][teams + i * _anongame_totalteams(queue)] = a->tc[i];
861 players[queue]++;
862 }
863 teams++;
864
865 /* check for enough players */
866 if (players[queue] == _anongame_totalplayers(queue)) {
867
868 /* unqueue just the single team entry */
869 for (i = 0; i < teams; i++)
870 anongame_unqueue(inv_c[i], queue);
871
872 mapname = _get_map_from_prefs(queue, cur_prefs, conn_get_clienttag(c));
873 return 0;
874 }
875
876 /* PG match */
877 } else {
878 player[queue][players[queue]++] = md->c;
879
880 if (players[queue] == _anongame_totalplayers(queue)) {
881 /* first sort queue by level */
882 qsort(player[queue], players[queue], sizeof(t_connection *), _anongame_compare_level);
883 /* next call reodering function */
884 _anongame_order_queue(queue);
885 /* unqueue players */
886 for (i = 0; i < players[queue]; i++)
887 anongame_unqueue(player[queue][i], queue);
888
889 mapname = _get_map_from_prefs(queue, cur_prefs, conn_get_clienttag(c));
890 return 0;
891 }
892 }
893 }
894 }
895 }
896
897 if (delta <= 0 || level - delta < 0)
898 delta = abs(delta) + 1;
899 else
900 delta = -delta;
901
902 if (level + delta > MAX_LEVEL)
903 delta = -delta;
904
905 if (level + delta < 0)
906 break; /* cant really happen */
907
908 }
909 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] Matching finished, not enough players (found %d)", conn_get_socket(c), players[queue]);
910 mapname = NULL;
911 return 0;
912 }
913
914 static int w3routeip = -1; /* changed by dizzy to show the w3routeshow addr if available */
915 static unsigned short w3routeport = BNETD_W3ROUTE_PORT;
916
_anongame_search_found(int queue)917 static int _anongame_search_found(int queue)
918 {
919 t_packet *rpacket;
920 t_anongameinfo *info;
921 t_anongame *a;
922 int i, j;
923 t_saf_pt2 *pt2;
924
925 /* FIXME: maybe periodically lookup w3routeaddr to support dynamic ips?
926 * (or should dns lookup be even quick enough to do it everytime?)
927 */
928
929 if (w3routeip == -1) {
930 t_addr *routeraddr;
931
932 routeraddr = addr_create_str(prefs_get_w3route_addr(), 0, BNETD_W3ROUTE_PORT);
933
934 if (!routeraddr) {
935 eventlog(eventlog_level_error, __FUNCTION__, "error getting w3route_addr");
936 return -1;
937 }
938
939 w3routeip = addr_get_ip(routeraddr);
940 w3routeport = addr_get_port(routeraddr);
941 addr_destroy(routeraddr);
942 }
943
944 info = anongameinfo_create(_anongame_totalplayers(queue));
945
946 if (!info) {
947 eventlog(eventlog_level_error, __FUNCTION__, "anongameinfo_create failed");
948 return -1;
949 }
950
951 /* create data to be appended to end of packet */
952 pt2 = xmalloc(sizeof(t_saf_pt2));
953 bn_int_set(&pt2->unknown1, 0xFFFFFFFF);
954 bn_int_set(&pt2->anongame_string, _anongame_get_gametype_tab(queue));
955 bn_byte_set(&pt2->totalplayers, _anongame_totalplayers(queue));
956 bn_byte_set(&pt2->totalteams, _anongame_totalteams(queue)); /* 1v1 & sffa are set to zero in _anongame_totalteams() */
957 bn_short_set(&pt2->unknown2, 0);
958 bn_byte_set(&pt2->visibility, 2); /* visibility. 0x01 - dark 0x02 - default */
959 bn_byte_set(&pt2->unknown3, 2);
960
961 /* send found packet to each of the players */
962 for (i = 0; i < players[queue]; i++) {
963 if (!(a = conn_get_anongame(player[queue][i]))) {
964 eventlog(eventlog_level_error, __FUNCTION__, "no anongame struct for queued player");
965 xfree(pt2);
966 return -1;
967 }
968
969 a->info = info;
970 a->playernum = i + 1;
971
972 for (j = 0; j < players[queue]; j++) {
973 a->info->player[j] = player[queue][j];
974 a->info->account[j] = conn_get_account(player[queue][j]);
975 }
976
977 if (!(rpacket = packet_create(packet_class_bnet))) {
978 xfree(pt2);
979 return -1;
980 }
981
982 packet_set_size(rpacket, sizeof(t_server_anongame_found));
983 packet_set_type(rpacket, SERVER_ANONGAME_FOUND);
984 bn_byte_set(&rpacket->u.server_anongame_found.option, 1);
985 bn_int_set(&rpacket->u.server_anongame_found.count, a->count);
986 bn_int_set(&rpacket->u.server_anongame_found.unknown1, 0);
987 { /* trans support */
988 unsigned int w3ip = w3routeip;
989 unsigned short w3port = w3routeport;
990
991 trans_net(conn_get_addr(player[queue][i]), &w3ip, &w3port);
992
993 /* if ip to send is 0.0.0.0 (which will not work anyway) try
994 * to guess the reachable IP of pvpgn by using the local
995 * endpoing address of the bnet class connection */
996 if (!w3ip)
997 w3ip = conn_get_real_local_addr(player[queue][i]);
998
999 bn_int_nset(&rpacket->u.server_anongame_found.ip, w3ip);
1000 bn_short_set(&rpacket->u.server_anongame_found.port, w3port);
1001 }
1002 bn_byte_set(&rpacket->u.server_anongame_found.unknown2, i + 1);
1003 bn_byte_set(&rpacket->u.server_anongame_found.unknown3, queue);
1004 bn_short_set(&rpacket->u.server_anongame_found.unknown4, 0);
1005 bn_int_set(&rpacket->u.server_anongame_found.id, 0xdeadbeef);
1006 bn_byte_set(&rpacket->u.server_anongame_found.unknown5, 6);
1007 bn_byte_set(&rpacket->u.server_anongame_found.type, a->type);
1008 bn_byte_set(&rpacket->u.server_anongame_found.gametype, a->gametype);
1009 packet_append_string(rpacket, mapname);
1010 packet_append_data(rpacket, pt2, sizeof(t_saf_pt2));
1011 conn_push_outqueue(player[queue][i], rpacket);
1012 packet_del_ref(rpacket);
1013 }
1014
1015 /* clear queue */
1016 players[queue] = 0;
1017 xfree(pt2);
1018 return 0;
1019 }
1020
1021 /**********************************************************************************/
1022 /* external functions */
1023 /**********************************************************************************/
anongame_matchlists_create()1024 extern int anongame_matchlists_create()
1025 {
1026 int i, j;
1027
1028 for (i = 0; i < ANONGAME_TYPES; i++) {
1029 for (j = 0; j < MAX_LEVEL; j++) {
1030 matchlists[i][j] = NULL;
1031 }
1032 }
1033 return 0;
1034 }
1035
anongame_matchlists_destroy()1036 extern int anongame_matchlists_destroy()
1037 {
1038 int i, j;
1039 for (i = 0; i < ANONGAME_TYPES; i++) {
1040 for (j = 0; j < MAX_LEVEL; j++) {
1041 if (matchlists[i][j]) {
1042 list_destroy(matchlists[i][j]);
1043 }
1044 }
1045 }
1046 return 0;
1047 }
1048
1049 /**********/
handle_anongame_search(t_connection * c,t_packet const * packet)1050 extern int handle_anongame_search(t_connection * c, t_packet const *packet)
1051 {
1052 return _handle_anongame_search(c, packet);
1053 }
1054
anongame_unqueue(t_connection * c,int queue)1055 extern int anongame_unqueue(t_connection * c, int queue)
1056 {
1057 int i;
1058 t_elem *curr;
1059 t_matchdata *md;
1060
1061 if (queue < 0) {
1062 eventlog(eventlog_level_error, __FUNCTION__, "got negative queue id (%d)", queue);
1063 return -1;
1064 }
1065
1066 if (queue >= ANONGAME_TYPES) {
1067 eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue);
1068 return -1;
1069 }
1070
1071 if (conn_get_anongame_search_starttime(c) != ((time_t) 0)) {
1072 average_anongame_search_time *= anongame_search_count;
1073 average_anongame_search_time += (long) difftime(time(NULL), conn_get_anongame_search_starttime(c));
1074 anongame_search_count++;
1075 average_anongame_search_time /= anongame_search_count;
1076 if (anongame_search_count > 20000)
1077 anongame_search_count = anongame_search_count / 2; /* to prevent an overflow of the average time */
1078 conn_set_anongame_search_starttime(c, ((time_t) 0));
1079 }
1080
1081 for (i = 0; i < MAX_LEVEL; i++) {
1082 if (matchlists[queue][i] == NULL)
1083 continue;
1084
1085 LIST_TRAVERSE(matchlists[queue][i], curr) {
1086 md = elem_get_data(curr);
1087 if (md->c == c) {
1088 eventlog(eventlog_level_trace, __FUNCTION__, "unqueued player [%d] level %d", conn_get_socket(c), i);
1089 list_remove_elem(matchlists[queue][i], &curr);
1090 xfree(md);
1091 return 0;
1092 }
1093 }
1094 }
1095
1096 /* Output error to log for PG queues, AT players are queued with single
1097 * entry. Because anongame_unqueue() is called for each player, only the first
1098 * time called will the team be removed, the rest are therefore not an error.
1099 * [Omega]
1100 */
1101 if (anongame_arranged(queue) == 0) {
1102 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] player not found in \"%s\" queue", conn_get_socket(c), _anongame_queue_to_string(queue));
1103 return -1;
1104 }
1105
1106 return 0;
1107 }
1108
1109 /**********/
anongame_arranged(int queue)1110 extern char anongame_arranged(int queue)
1111 {
1112 switch (queue) {
1113 case ANONGAME_TYPE_AT_2V2:
1114 case ANONGAME_TYPE_AT_3V3:
1115 case ANONGAME_TYPE_AT_4V4:
1116 case ANONGAME_TYPE_AT_2V2V2:
1117 return 1;
1118 case ANONGAME_TYPE_TY:
1119 return tournament_is_arranged();
1120 default:
1121 return 0;
1122 }
1123 }
1124
anongame_evaluate_results(t_anongame * anongame)1125 extern int anongame_evaluate_results(t_anongame * anongame)
1126 {
1127 int i, j, number;
1128 int wins[ANONGAME_MAX_GAMECOUNT];
1129 int losses[ANONGAME_MAX_GAMECOUNT];
1130 int result;
1131 t_anongame_gameresult *results;
1132 t_anongameinfo *anoninfo = anongame->info;
1133
1134 for (i = 0; i < ANONGAME_MAX_GAMECOUNT; i++) {
1135 wins[i] = 0;
1136 losses[i] = 0;
1137 }
1138
1139 for (i = 0; i < anongame_get_totalplayers(anongame); i++) {
1140 if ((results = anoninfo->results[i])) {
1141 for (j = 0; j < gameresult_get_number_of_results(results); j++) {
1142 number = gameresult_get_player_number(results, j) - 1;
1143 result = gameresult_get_player_result(results, j);
1144
1145 if ((result == W3_GAMERESULT_WIN))
1146 wins[number]++;
1147 if ((result == W3_GAMERESULT_LOSS))
1148 losses[number]++;
1149 }
1150 }
1151 }
1152
1153 for (i = 0; i < anongame_get_totalplayers(anongame); i++) {
1154 if ((wins[i] > losses[i])) {
1155 if ((anoninfo->result[i] != W3_GAMERESULT_WIN)) {
1156 eventlog(eventlog_level_trace, __FUNCTION__, "player %d reported DISC/LOSS for self, but others agree on WIN", i + 1);
1157 anoninfo->result[i] = W3_GAMERESULT_WIN;
1158 }
1159 } else {
1160 if ((anoninfo->result[i] != W3_GAMERESULT_LOSS)) {
1161 eventlog(eventlog_level_trace, __FUNCTION__, "player %d reported DISC/WIN for self, but others agree on LOSS", i + 1);
1162 anoninfo->result[i] = W3_GAMERESULT_LOSS;
1163 }
1164 }
1165 }
1166
1167 return 0;
1168
1169 }
1170
anongame_stats(t_connection * c)1171 extern int anongame_stats(t_connection * c)
1172 {
1173 int i;
1174 int wins = 0, losses = 0, discs = 0;
1175 t_connection *gamec = conn_get_routeconn(c);
1176 t_anongame *a = conn_get_anongame(gamec);
1177 int tp = anongame_get_totalplayers(a);
1178 int oppon_level[ANONGAME_MAX_GAMECOUNT];
1179 t_uint8 gametype = a->queue;
1180 t_uint8 plnum = a->playernum;
1181 t_clienttag ct = conn_get_clienttag(c);
1182 int tt = _anongame_totalteams(gametype);
1183
1184 /* do nothing till all other players have w3route conn closed */
1185 for (i = 0; i < tp; i++)
1186 if (i + 1 != plnum && a->info->player[i])
1187 if (conn_get_routeconn(a->info->player[i]))
1188 return 0;
1189
1190 anongame_evaluate_results(a);
1191
1192 /* count wins, losses, discs */
1193 for (i = 0; i < tp; i++) {
1194 if (a->info->result[i] == W3_GAMERESULT_WIN)
1195 wins++;
1196 else if (a->info->result[i] == W3_GAMERESULT_LOSS)
1197 losses++;
1198 else
1199 discs++;
1200 }
1201
1202 /* do some sanity checking (hack prevention) */
1203 switch (gametype) {
1204 case ANONGAME_TYPE_SMALL_FFA:
1205 if (wins != 1) {
1206 eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins != 1 in small ffa game");
1207 return -1;
1208 }
1209 break;
1210 case ANONGAME_TYPE_TEAM_FFA:
1211 if (!discs && wins != 2) {
1212 eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins != 2 in team ffa game");
1213 return -1;
1214 }
1215 break;
1216 default:
1217 if (!discs && wins > losses) {
1218 eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins > losses");
1219 return -1;
1220 }
1221 break;
1222 }
1223
1224 /* prevent users from getting loss if server is shutdown (does not prevent errors from crash) - [Omega] */
1225 /* also discard games with no winners at all (i.e. games where game host disc'ed and so all players do) */
1226 if (!wins)
1227 return -1;
1228
1229 /* according to zap, order of players in anongame is:
1230 * for PG: t1_p1, t2_p1, t1_p2, t2_p2, ...
1231 * for AT: t1_p1, t1_p2, ..., t2_p1, t2_p2, ...
1232 *
1233 * (Not True.. follows same order as PG)
1234 * 4v4 = t1_p1, t2_p1, t1_p2, t2_p2, t1_p3, t2_p3, t1_p4, t2_p4
1235 * 3v3v3 = t1_p1, t2_p1, t3_p1, t1_p2, t2_p2, t3_p2, t1_p3, t2_p3, t3_p3
1236 * 2v2v2v2 = t1_p1, t2_p1, t3_p1, t4_p1, t1_p2, t2_p2, t3_p2, t4_p2
1237 */
1238
1239 /* opponent level calculation has to be done here, because later on, the level of other players
1240 * may allready be modified
1241 */
1242 for (i = 0; i < tp; i++) {
1243 int j, k, l;
1244 t_account *oacc;
1245 oppon_level[i] = 0;
1246 switch (gametype) {
1247 case ANONGAME_TYPE_TY:
1248 /* FIXME-TY: ADD TOURNAMENT STATS RECORDING (this part not required?) */
1249 break;
1250 case ANONGAME_TYPE_1V1:
1251 oppon_level[i] = account_get_ladder_level(a->info->account[(i + 1) % tp], ct, ladder_id_solo);
1252 break;
1253 case ANONGAME_TYPE_SMALL_FFA:
1254 /* oppon_level = average level of all other players */
1255 for (j = 0; j < tp; j++)
1256 if (i != j)
1257 oppon_level[i] += account_get_ladder_level(a->info->account[j], ct, ladder_id_ffa);
1258 oppon_level[i] /= (tp - 1);
1259 break;
1260 case ANONGAME_TYPE_AT_2V2:
1261 case ANONGAME_TYPE_AT_3V3:
1262 case ANONGAME_TYPE_AT_4V4:
1263 oacc = a->info->account[(i + 1) % tp];
1264 oppon_level[i] = team_get_level(account_find_team_by_teamid(oacc, account_get_currentatteam(oacc)));
1265 break;
1266 case ANONGAME_TYPE_AT_2V2V2:
1267 oacc = a->info->account[(i + 1) % tp];
1268 oppon_level[i] = team_get_level(account_find_team_by_teamid(oacc, account_get_currentatteam(oacc)));
1269 oacc = a->info->account[(i + 2) % tp];
1270 oppon_level[i] = team_get_level(account_find_team_by_teamid(oacc, account_get_currentatteam(oacc)));
1271 oppon_level[i] /= 2;
1272 break;
1273 default:
1274 /* oppon_level = average level of all opponents
1275 * this should work for all PG team games
1276 * [Omega] */
1277 k = i + 1;
1278 for (j = 0; j < (tp / tt); j++) {
1279 for (l = 0; l < (tt - 1); l++) {
1280 oppon_level[i] += account_get_ladder_level(a->info->account[k % tp], ct, ladder_id_team);
1281 k++;
1282 }
1283 k++;
1284 }
1285 oppon_level[i] /= (tp / tt * (tt - 1));
1286 }
1287 }
1288
1289 for (i = 0; i < tp; i++) {
1290 t_account *acc;
1291 t_team *team;
1292 unsigned int currteam;
1293 int result = a->info->result[i];
1294
1295 if (result == -1)
1296 result = W3_GAMERESULT_LOSS;
1297
1298 acc = a->info->account[i];
1299
1300 switch (gametype) {
1301 case ANONGAME_TYPE_TY:
1302 if (result == W3_GAMERESULT_WIN)
1303 tournament_add_stat(acc, 1);
1304 if (result == W3_GAMERESULT_LOSS)
1305 tournament_add_stat(acc, 2);
1306 /* FIXME-TY: how to do ties? */
1307 break;
1308 case ANONGAME_TYPE_AT_2V2:
1309 case ANONGAME_TYPE_AT_3V3:
1310 case ANONGAME_TYPE_AT_4V4:
1311 case ANONGAME_TYPE_AT_2V2V2:
1312
1313 if ((currteam = account_get_currentatteam(acc))) {
1314 team = account_find_team_by_teamid(acc, currteam);
1315 team_set_saveladderstats(team, gametype, result, oppon_level[i], ct);
1316 }
1317
1318 break;
1319 case ANONGAME_TYPE_1V1:
1320 case ANONGAME_TYPE_2V2:
1321 case ANONGAME_TYPE_3V3:
1322 case ANONGAME_TYPE_4V4:
1323 case ANONGAME_TYPE_SMALL_FFA:
1324 case ANONGAME_TYPE_5V5:
1325 case ANONGAME_TYPE_6V6:
1326 case ANONGAME_TYPE_2V2V2:
1327 case ANONGAME_TYPE_3V3V3:
1328 case ANONGAME_TYPE_4V4V4:
1329 case ANONGAME_TYPE_2V2V2V2:
1330 case ANONGAME_TYPE_3V3V3V3:
1331 if (result == W3_GAMERESULT_WIN)
1332 account_set_saveladderstats(acc, gametype, game_result_win, oppon_level[i], ct);
1333 if (result == W3_GAMERESULT_LOSS)
1334 account_set_saveladderstats(acc, gametype, game_result_loss, oppon_level[i], ct);
1335 break;
1336 default:
1337 break;
1338 }
1339 }
1340 /* aaron: now update war3 ladders */
1341 ladder_update_all_accounts();
1342 return 1;
1343 }
1344
1345 /**********/
anongameinfo_create(int totalplayers)1346 extern t_anongameinfo *anongameinfo_create(int totalplayers)
1347 {
1348 t_anongameinfo *temp;
1349 int i;
1350
1351 temp = xmalloc(sizeof(t_anongameinfo));
1352
1353 temp->totalplayers = temp->currentplayers = totalplayers;
1354 for (i = 0; i < ANONGAME_MAX_GAMECOUNT; i++) {
1355 temp->player[i] = NULL;
1356 temp->account[i] = NULL;
1357 temp->result[i] = -1; /* consider DISC default */
1358 temp->results[i] = NULL;
1359 }
1360
1361 return temp;
1362 }
1363
anongameinfo_destroy(t_anongameinfo * i)1364 extern void anongameinfo_destroy(t_anongameinfo * i)
1365 {
1366 int j;
1367
1368 if (!i) {
1369 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongameinfo");
1370 return;
1371 }
1372 for (j = 0; j < ANONGAME_MAX_GAMECOUNT; j++)
1373 if (i->results[j])
1374 gameresult_destroy(i->results[j]);
1375 xfree(i);
1376 }
1377
1378 /**********/
anongame_get_info(t_anongame * a)1379 extern t_anongameinfo *anongame_get_info(t_anongame * a)
1380 {
1381 if (!a) {
1382 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1383 return NULL;
1384 }
1385
1386 return a->info;
1387 }
1388
anongame_get_currentplayers(t_anongame * a)1389 extern int anongame_get_currentplayers(t_anongame * a)
1390 {
1391 if (!a) {
1392 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1393 return 0;
1394 }
1395 if (!a->info) {
1396 eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo");
1397 return 0;
1398 }
1399
1400 return a->info->currentplayers;
1401 }
1402
anongame_get_totalplayers(t_anongame * a)1403 extern int anongame_get_totalplayers(t_anongame * a)
1404 {
1405 if (!a) {
1406 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1407 return 0;
1408 }
1409 if (!a->info) {
1410 eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo");
1411 return 0;
1412 }
1413
1414 return a->info->totalplayers;
1415 }
1416
anongame_get_player(t_anongame * a,int plnum)1417 extern t_connection *anongame_get_player(t_anongame * a, int plnum)
1418 {
1419 if (!a) {
1420 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1421 return NULL;
1422 }
1423 if (!a->info) {
1424 eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo");
1425 return NULL;
1426 }
1427
1428 if (plnum < 0 || plnum > 7 || plnum >= a->info->totalplayers) {
1429 eventlog(eventlog_level_error, __FUNCTION__, "invalid plnum: %d", plnum);
1430 return NULL;
1431 }
1432
1433 return a->info->player[plnum];
1434 }
1435
anongame_get_count(t_anongame * a)1436 extern int anongame_get_count(t_anongame * a)
1437 {
1438 if (!a) {
1439 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1440 return 0;
1441 }
1442 return a->count;
1443 }
1444
anongame_get_id(t_anongame * a)1445 extern t_uint32 anongame_get_id(t_anongame * a)
1446 {
1447 if (!a) {
1448 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1449 return 0;
1450 }
1451 return a->id;
1452 }
1453
anongame_get_tc(t_anongame * a,int tpnumber)1454 extern t_connection *anongame_get_tc(t_anongame * a, int tpnumber)
1455 {
1456 if (!a) {
1457 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1458 return 0;
1459 }
1460 return a->tc[tpnumber];
1461 }
1462
anongame_get_race(t_anongame * a)1463 extern t_uint32 anongame_get_race(t_anongame * a)
1464 {
1465 if (!a) {
1466 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1467 return 0;
1468 }
1469 return a->race;
1470 }
1471
anongame_get_handle(t_anongame * a)1472 extern t_uint32 anongame_get_handle(t_anongame * a)
1473 {
1474 if (!a) {
1475 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1476 return 0;
1477 }
1478 return a->handle;
1479 }
1480
anongame_get_addr(t_anongame * a)1481 extern unsigned int anongame_get_addr(t_anongame * a)
1482 {
1483 if (!a) {
1484 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1485 return 0;
1486 }
1487 return a->addr;
1488 }
1489
anongame_get_loaded(t_anongame * a)1490 extern char anongame_get_loaded(t_anongame * a)
1491 {
1492 if (!a) {
1493 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1494 return 0;
1495 }
1496 return a->loaded;
1497 }
1498
anongame_get_joined(t_anongame * a)1499 extern char anongame_get_joined(t_anongame * a)
1500 {
1501 if (!a) {
1502 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1503 return 0;
1504 }
1505 return a->joined;
1506 }
1507
anongame_get_playernum(t_anongame * a)1508 extern t_uint8 anongame_get_playernum(t_anongame * a)
1509 {
1510 if (!a) {
1511 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1512 return 0;
1513 }
1514 return a->playernum;
1515 }
1516
anongame_get_queue(t_anongame * a)1517 extern t_uint8 anongame_get_queue(t_anongame * a)
1518 {
1519 if (!a) {
1520 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1521 return 0;
1522 }
1523 return a->queue;
1524 }
1525
1526 /**********/
anongame_set_result(t_anongame * a,int result)1527 extern void anongame_set_result(t_anongame * a, int result)
1528 {
1529 if (!a) {
1530 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1531 return;
1532 }
1533 if (!a->info) {
1534 eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo");
1535 return;
1536 }
1537
1538 if (a->playernum < 1 || a->playernum > ANONGAME_MAX_GAMECOUNT) {
1539 eventlog(eventlog_level_error, __FUNCTION__, "invalid playernum: %d", a->playernum);
1540 return;
1541 }
1542
1543 a->info->result[a->playernum - 1] = result;
1544 }
1545
anongame_set_gameresults(t_anongame * a,t_anongame_gameresult * results)1546 extern void anongame_set_gameresults(t_anongame * a, t_anongame_gameresult * results)
1547 {
1548 if (!a) {
1549 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1550 return;
1551 }
1552 if (!a->info) {
1553 eventlog(eventlog_level_error, __FUNCTION__, "NULL anongameinfo");
1554 return;
1555 }
1556
1557 if (a->playernum < 1 || a->playernum > ANONGAME_MAX_GAMECOUNT) {
1558 eventlog(eventlog_level_error, __FUNCTION__, "invalid playernum: %d", a->playernum);
1559 return;
1560 }
1561
1562 a->info->results[a->playernum - 1] = results;
1563 }
1564
anongame_set_handle(t_anongame * a,t_uint32 h)1565 extern void anongame_set_handle(t_anongame * a, t_uint32 h)
1566 {
1567 if (!a) {
1568 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1569 return;
1570 }
1571
1572 a->handle = h;
1573 }
1574
anongame_set_addr(t_anongame * a,unsigned int addr)1575 extern void anongame_set_addr(t_anongame * a, unsigned int addr)
1576 {
1577 if (!a) {
1578 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1579 return;
1580 }
1581
1582 a->addr = addr;
1583 }
1584
anongame_set_loaded(t_anongame * a,char loaded)1585 extern void anongame_set_loaded(t_anongame * a, char loaded)
1586 {
1587 if (!a) {
1588 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1589 return;
1590 }
1591
1592 a->loaded = loaded;
1593 }
1594
anongame_set_joined(t_anongame * a,char joined)1595 extern void anongame_set_joined(t_anongame * a, char joined)
1596 {
1597 if (!a) {
1598 eventlog(eventlog_level_error, __FUNCTION__, "got NULL anongame");
1599 return;
1600 }
1601
1602 a->joined = joined;
1603 }
1604
1605 /**********/
1606 /* move to own .c/.h file for handling w3route connections */
handle_w3route_packet(t_connection * c,t_packet const * const packet)1607 extern int handle_w3route_packet(t_connection * c, t_packet const *const packet)
1608 {
1609 /* [smith] 20030427 fixed Big-Endian/Little-Endian conversion (Solaris bug) then
1610 * use packet_append_data for append platform dependent data types - like
1611 * "int", cos this code was broken for BE platforms. it's rewriten in platform
1612 * independent style whis usege bn_int and other bn_* like datatypes and
1613 * fuctions for wor with datatypes - bn_int_set(), what provide right
1614 * byteorder, not depended on LE/BE
1615 * fixed broken htonl() conversion for BE platforms - change it to
1616 * bn_int_nset(). i hope it's worked on intel too %) */
1617
1618 t_packet *rpacket;
1619 t_connection *gamec;
1620 char const *username;
1621 t_anongame *a = NULL;
1622 t_uint8 gametype, plnum;
1623 int tp, i;
1624
1625 if (!c) {
1626 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(c));
1627 return -1;
1628 }
1629 if (!packet) {
1630 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL packet", conn_get_socket(c));
1631 return -1;
1632 }
1633 if (packet_get_class(packet) != packet_class_w3route) {
1634 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad packet (class %d)", conn_get_socket(c), packet_get_class(packet));
1635 return -1;
1636 }
1637 if (conn_get_state(c) != conn_state_connected) {
1638 eventlog(eventlog_level_error, __FUNCTION__, "[%d] not connected", conn_get_socket(c));
1639 return -1;
1640 }
1641
1642 /* init route connection */
1643 if (packet_get_type(packet) == CLIENT_W3ROUTE_REQ) {
1644 t_connection *oldc;
1645
1646 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] sizeof t_client_w3route_req %d", conn_get_socket(c), sizeof(t_client_w3route_req));
1647 username = packet_get_str_const(packet, sizeof(t_client_w3route_req), USER_NAME_MAX);
1648 eventlog(eventlog_level_info, __FUNCTION__, "[%d] got username '%s'", conn_get_socket(c), username);
1649 gamec = connlist_find_connection_by_accountname(username);
1650
1651 if (!gamec) {
1652 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no game connection found for this w3route connection; closing", conn_get_socket(c));
1653 conn_set_state(c, conn_state_destroy);
1654 return 0;
1655 }
1656
1657 if (!(a = conn_get_anongame(gamec))) {
1658 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no anongame struct for game connection", conn_get_socket(c));
1659 conn_set_state(c, conn_state_destroy);
1660 return 0;
1661 }
1662
1663 if (bn_int_get((unsigned char const *) packet->u.data + sizeof(t_client_w3route_req) + strlen(username) + 2) != anongame_get_id(a)) {
1664 eventlog(eventlog_level_info, __FUNCTION__, "[%d] client sent wrong id for user '%s', closing connection", conn_get_socket(c), username);
1665 conn_set_state(c, conn_state_destroy);
1666 return 0;
1667 }
1668
1669 oldc = conn_get_routeconn(gamec);
1670 if (oldc) {
1671 conn_set_routeconn(oldc, NULL);
1672 conn_set_state(oldc, conn_state_destroy);
1673 }
1674
1675 if (conn_set_routeconn(c, gamec) < 0 || conn_set_routeconn(gamec, c) < 0) {
1676 eventlog(eventlog_level_error, __FUNCTION__, "[%d] conn_set_routeconn failed", conn_get_socket(c));
1677 return -1;
1678 }
1679
1680 /* set clienttag for w3route connections; we can do conn_get_clienttag() on them */
1681 conn_set_clienttag(c, conn_get_clienttag(gamec));
1682
1683 anongame_set_addr(a, bn_int_get((unsigned char const *) packet->u.data + sizeof(t_client_w3route_req) + strlen(username) + 2 + 12));
1684 anongame_set_joined(a, 0);
1685 anongame_set_loaded(a, 0);
1686 anongame_set_result(a, -1);
1687 anongame_set_gameresults(a, NULL);
1688
1689 anongame_set_handle(a, bn_int_get(packet->u.client_w3route_req.handle));
1690
1691 if (!(rpacket = packet_create(packet_class_w3route))) {
1692 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
1693 return -1;
1694 }
1695
1696 packet_set_size(rpacket, sizeof(t_server_w3route_ack));
1697 packet_set_type(rpacket, SERVER_W3ROUTE_ACK);
1698 bn_byte_set(&rpacket->u.server_w3route_ack.unknown1, 7);
1699 bn_short_set(&rpacket->u.server_w3route_ack.unknown2, 0);
1700 bn_int_set(&rpacket->u.server_w3route_ack.unknown3, SERVER_W3ROUTE_ACK_UNKNOWN3);
1701
1702 bn_short_set(&rpacket->u.server_w3route_ack.unknown4, 0xcccc);
1703 bn_byte_set(&rpacket->u.server_w3route_ack.playernum, anongame_get_playernum(a));
1704 bn_short_set(&rpacket->u.server_w3route_ack.unknown5, 0x0002);
1705 bn_short_set(&rpacket->u.server_w3route_ack.port, conn_get_port(c));
1706 bn_int_nset(&rpacket->u.server_w3route_ack.ip, conn_get_addr(c));
1707 bn_int_set(&rpacket->u.server_w3route_ack.unknown7, 0);
1708 bn_int_set(&rpacket->u.server_w3route_ack.unknown8, 0);
1709 conn_push_outqueue(c, rpacket);
1710 packet_del_ref(rpacket);
1711
1712 return 0;
1713 } else {
1714 gamec = conn_get_routeconn(c);
1715 if (gamec)
1716 a = conn_get_anongame(gamec);
1717 }
1718
1719 if (!gamec) {
1720 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no game connection found for this w3route connection", conn_get_socket(c));
1721 return 0;
1722 }
1723
1724 if (!a) {
1725 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no anongame struct found for this w3route connection", conn_get_socket(c));
1726 return 0;
1727 }
1728
1729 gametype = anongame_get_queue(a);
1730 plnum = anongame_get_playernum(a);
1731 tp = anongame_get_totalplayers(a);
1732
1733 /* handle these packets _before_ checking for routeconn of other players */
1734 switch (packet_get_type(packet)) {
1735 case CLIENT_W3ROUTE_ECHOREPLY:
1736 return 0;
1737 case CLIENT_W3ROUTE_CONNECTED:
1738 return 0;
1739 case CLIENT_W3ROUTE_GAMERESULT:
1740 case CLIENT_W3ROUTE_GAMERESULT_W3XP:
1741 {
1742
1743 /* insert reading of whole packet into t_gameresult */
1744
1745 t_anongame_gameresult *gameresult;
1746 int result;
1747
1748 t_timer_data data;
1749 t_anongameinfo *inf = anongame_get_info(a);
1750 t_connection *ac;
1751
1752 data.p = NULL;
1753
1754 if (!(gameresult = anongame_gameresult_parse(packet)))
1755 result = -1;
1756 else /* own result is always stored as first result */
1757 result = gameresult_get_player_result(gameresult, 0);
1758
1759 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] got W3ROUTE_GAMERESULT: %08x", conn_get_socket(c), result);
1760
1761 if (!inf) {
1762 eventlog(eventlog_level_error, __FUNCTION__, "[%d] NULL anongameinfo", conn_get_socket(c));
1763 return -1;
1764 }
1765
1766 anongame_set_gameresults(a, gameresult);
1767 anongame_set_result(a, result);
1768
1769 conn_set_state(c, conn_state_destroy);
1770
1771 /* activate timers on open w3route connectons */
1772 if (result == W3_GAMERESULT_WIN) {
1773 for (i = 0; i < tp; i++) {
1774 if (anongame_get_player(a, i)) {
1775 ac = conn_get_routeconn(anongame_get_player(a, i));
1776 if (ac) {
1777 /* 300 seconds or 5 minute timer */
1778 timerlist_add_timer(ac, now + (time_t) 300, conn_shutdown, data);
1779 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] started timer to close w3route", conn_get_socket(ac));
1780 }
1781 }
1782 }
1783 }
1784
1785 return 0;
1786 }
1787 }
1788
1789 for (i = 0; i < tp; i++)
1790 if (i + 1 != plnum && anongame_get_player(a, i))
1791 if (!conn_get_routeconn(anongame_get_player(a, i)) || !conn_get_anongame(anongame_get_player(a, i))) {
1792 eventlog(eventlog_level_info, __FUNCTION__, "[%d] not all players have w3route connections up yet", conn_get_socket(c));
1793 return 0;
1794 }
1795
1796 /* handle these packets _after_ checking for routeconns of other players */
1797 switch (packet_get_type(packet)) {
1798 case CLIENT_W3ROUTE_LOADINGDONE:
1799 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] got LOADINGDONE, playernum: %d", conn_get_socket(c), plnum);
1800
1801 anongame_set_loaded(a, 1);
1802
1803 for (i = 0; i < tp; i++) {
1804 if (!anongame_get_player(a, i)) /* ignore disconnected players */
1805 continue;
1806 if (!(rpacket = packet_create(packet_class_w3route))) {
1807 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
1808 return -1;
1809 }
1810 packet_set_size(rpacket, sizeof(t_server_w3route_loadingack));
1811 packet_set_type(rpacket, SERVER_W3ROUTE_LOADINGACK);
1812 bn_byte_set(&rpacket->u.server_w3route_loadingack.playernum, plnum);
1813 conn_push_outqueue(conn_get_routeconn(anongame_get_player(a, i)), rpacket);
1814 packet_del_ref(rpacket);
1815 }
1816
1817 /* have all players loaded? */
1818 for (i = 0; i < tp; i++)
1819 if (i + 1 != plnum && anongame_get_player(a, i) && !anongame_get_loaded(conn_get_anongame(anongame_get_player(a, i))))
1820 return 0;
1821
1822 for (i = 0; i < tp; i++) {
1823 if (!anongame_get_player(a, i))
1824 continue;
1825
1826 if (!(rpacket = packet_create(packet_class_w3route))) {
1827 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
1828 return -1;
1829 }
1830
1831 packet_set_size(rpacket, sizeof(t_server_w3route_ready));
1832 packet_set_type(rpacket, SERVER_W3ROUTE_READY);
1833 bn_byte_set(&rpacket->u.server_w3route_host.unknown1, 0);
1834 conn_push_outqueue(conn_get_routeconn(anongame_get_player(a, i)), rpacket);
1835 packet_del_ref(rpacket);
1836 }
1837
1838 break;
1839
1840 case CLIENT_W3ROUTE_ABORT:
1841 eventlog(eventlog_level_debug, __FUNCTION__, "[%d] got W3ROUTE_ABORT", conn_get_socket(c));
1842 break;
1843
1844 default:
1845 eventlog(eventlog_level_trace, __FUNCTION__, "[%d] default: got packet type: %04x", conn_get_socket(c), packet_get_type(packet));
1846 }
1847
1848 return 0;
1849 }
1850
handle_anongame_join(t_connection * c)1851 extern int handle_anongame_join(t_connection * c)
1852 {
1853 t_anongame *a, *ja, *oa;
1854 t_connection *jc, *o;
1855 t_packet *rpacket;
1856 int tp, level;
1857 char gametype;
1858 t_account *acct;
1859 t_clienttag ct = conn_get_clienttag(c);
1860
1861 static t_server_w3route_playerinfo2 pl2;
1862 static t_server_w3route_levelinfo2 li2;
1863 static t_server_w3route_playerinfo_addr pl_addr;
1864
1865 int i, j;
1866
1867 if (!c) {
1868 eventlog(eventlog_level_error, __FUNCTION__, "[%d] got NULL connection", conn_get_socket(c));
1869 return -1;
1870 }
1871 if (!(conn_get_routeconn(c))) {
1872 eventlog(eventlog_level_info, __FUNCTION__, "[%d] no route connection", conn_get_socket(c));
1873 return -1;
1874 }
1875 if (!(a = conn_get_anongame(c))) {
1876 eventlog(eventlog_level_error, __FUNCTION__, "[%d] no anongame struct", conn_get_socket(c));
1877 return -1;
1878 }
1879
1880 anongame_set_joined(a, 1);
1881 gametype = anongame_get_queue(a);
1882 tp = anongame_get_totalplayers(a);
1883
1884 /* wait till all players have w3route conns */
1885 for (i = 0; i < tp; i++)
1886 if (anongame_get_player(a, i) && (!conn_get_routeconn(anongame_get_player(a, i)) || !conn_get_anongame(anongame_get_player(a, i)) || !anongame_get_joined(conn_get_anongame(anongame_get_player(a, i))))) {
1887 eventlog(eventlog_level_info, __FUNCTION__, "[%d] not all players have joined game BNet yet", conn_get_socket(c));
1888 return 0;
1889 }
1890
1891 /* then send each player info about all others */
1892 for (j = 0; j < tp; j++) {
1893 jc = anongame_get_player(a, j);
1894 if (!jc) /* ignore disconnected players */
1895 continue;
1896 ja = conn_get_anongame(jc);
1897
1898 /* send a playerinfo packet for this player to each other player */
1899 for (i = 0; i < tp; i++) {
1900 if (i + 1 != anongame_get_playernum(ja)) {
1901 eventlog(eventlog_level_trace, __FUNCTION__, "i = %d", i);
1902
1903 if (!(o = anongame_get_player(ja, i))) {
1904 eventlog(eventlog_level_warn, __FUNCTION__, "[%d] player %d disconnected, ignoring", conn_get_socket(c), i);
1905 continue;
1906 }
1907
1908 if (!(rpacket = packet_create(packet_class_w3route))) {
1909 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
1910 return -1;
1911 }
1912
1913 packet_set_size(rpacket, sizeof(t_server_w3route_playerinfo));
1914 packet_set_type(rpacket, SERVER_W3ROUTE_PLAYERINFO);
1915
1916
1917 if (!(oa = conn_get_anongame(o))) {
1918 eventlog(eventlog_level_error, __FUNCTION__, "[%d] no anongame struct of player %d", conn_get_socket(c), i);
1919 return -1;
1920 }
1921
1922 bn_int_set(&rpacket->u.server_w3route_playerinfo.handle, anongame_get_handle(oa));
1923 bn_byte_set(&rpacket->u.server_w3route_playerinfo.playernum, anongame_get_playernum(oa));
1924
1925 packet_append_string(rpacket, conn_get_username(o));
1926
1927 /* playerinfo2 */
1928 bn_byte_set(&pl2.unknown1, 8);
1929 bn_int_set(&pl2.id, anongame_get_id(oa));
1930 bn_int_set(&pl2.race, anongame_get_race(oa));
1931 packet_append_data(rpacket, &pl2, sizeof(pl2));
1932
1933 /* external addr */
1934 bn_short_set(&pl_addr.unknown1, 2);
1935 { /* trans support */
1936 unsigned short port = conn_get_game_port(o);
1937 unsigned int addr = conn_get_game_addr(o);
1938
1939 trans_net(conn_get_game_addr(jc), &addr, &port);
1940
1941 bn_short_nset(&pl_addr.port, port);
1942 bn_int_nset(&pl_addr.ip, addr);
1943 }
1944 bn_int_set(&pl_addr.unknown2, 0);
1945 bn_int_set(&pl_addr.unknown3, 0);
1946 packet_append_data(rpacket, &pl_addr, sizeof(pl_addr));
1947
1948 /* local addr */
1949 bn_short_set(&pl_addr.unknown1, 2);
1950 bn_short_nset(&pl_addr.port, conn_get_game_port(o));
1951 bn_int_set(&pl_addr.ip, anongame_get_addr(oa));
1952 bn_int_set(&pl_addr.unknown2, 0);
1953 bn_int_set(&pl_addr.unknown3, 0);
1954 packet_append_data(rpacket, &pl_addr, sizeof(pl_addr));
1955
1956 conn_push_outqueue(conn_get_routeconn(jc), rpacket);
1957 packet_del_ref(rpacket);
1958 }
1959 }
1960
1961 /* levelinfo */
1962 if (!(rpacket = packet_create(packet_class_w3route))) {
1963 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
1964 return -1;
1965 }
1966
1967 packet_set_size(rpacket, sizeof(t_server_w3route_levelinfo));
1968 packet_set_type(rpacket, SERVER_W3ROUTE_LEVELINFO);
1969 bn_byte_set(&rpacket->u.server_w3route_levelinfo.numplayers, anongame_get_currentplayers(a));
1970
1971 for (i = 0; i < tp; i++) {
1972 if (!anongame_get_player(ja, i))
1973 continue;
1974
1975 bn_byte_set(&li2.plnum, i + 1);
1976 bn_byte_set(&li2.unknown1, 3);
1977
1978 switch (gametype) {
1979 case ANONGAME_TYPE_1V1:
1980 level = account_get_ladder_level(conn_get_account(anongame_get_player(ja, i)), ct, ladder_id_solo);
1981 break;
1982 case ANONGAME_TYPE_SMALL_FFA:
1983 case ANONGAME_TYPE_TEAM_FFA:
1984 level = account_get_ladder_level(conn_get_account(anongame_get_player(ja, i)), ct, ladder_id_ffa);
1985 break;
1986 case ANONGAME_TYPE_AT_2V2:
1987 case ANONGAME_TYPE_AT_3V3:
1988 case ANONGAME_TYPE_AT_4V4:
1989 case ANONGAME_TYPE_AT_2V2V2:
1990 acct = conn_get_account(anongame_get_player(ja, i));
1991 level = team_get_level(account_find_team_by_teamid(acct, account_get_currentatteam(acct)));
1992 break;
1993 case ANONGAME_TYPE_TY:
1994 level = 0; /* FIXME-TY: WHAT TO DO HERE */
1995 break;
1996 default:
1997 level = account_get_ladder_level(conn_get_account(anongame_get_player(ja, i)), ct, ladder_id_team);
1998 break;
1999 }
2000
2001 /* first anongame shows level 0 as level 1 */
2002 bn_byte_set(&li2.level, level ? level : 1);
2003
2004 bn_short_set(&li2.unknown2, 0);
2005 packet_append_data(rpacket, &li2, sizeof(li2));
2006 }
2007
2008 conn_push_outqueue(conn_get_routeconn(jc), rpacket);
2009 packet_del_ref(rpacket);
2010
2011 /* startgame1 */
2012 if (!(rpacket = packet_create(packet_class_w3route))) {
2013 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
2014 return -1;
2015 }
2016 packet_set_size(rpacket, sizeof(t_server_w3route_startgame1));
2017 packet_set_type(rpacket, SERVER_W3ROUTE_STARTGAME1);
2018 conn_push_outqueue(conn_get_routeconn(jc), rpacket);
2019 packet_del_ref(rpacket);
2020
2021 /* startgame2 */
2022 if (!(rpacket = packet_create(packet_class_w3route))) {
2023 eventlog(eventlog_level_error, __FUNCTION__, "[%d] packet_create failed", conn_get_socket(c));
2024 return -1;
2025 }
2026 packet_set_size(rpacket, sizeof(t_server_w3route_startgame2));
2027 packet_set_type(rpacket, SERVER_W3ROUTE_STARTGAME2);
2028 conn_push_outqueue(conn_get_routeconn(jc), rpacket);
2029 packet_del_ref(rpacket);
2030 }
2031 return 0;
2032 }
2033