/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/anongame.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/anongame.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

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

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1