static int d2charsave_init(void * buffer,char const * charname,unsigned char classs,unsigned short status) { ASSERT(buffer,-1); ASSERT(charname,-1); bn_byte_set((bn_byte *)((char *)buffer+D2CHARSAVE_CLASS_OFFSET), classs); bn_short_set((bn_short *)((char *)buffer+D2CHARSAVE_STATUS_OFFSET),status); strncpy((char *)buffer+D2CHARSAVE_CHARNAME_OFFSET,charname,MAX_CHARNAME_LEN); return 0; }
static int on_client_gameinforeq(t_connection * c, t_packet * packet) { t_game_charinfo * info; t_packet * rpacket; char const * gamename; t_game * game; unsigned int seqno, n; if (!(gamename=packet_get_str_const(packet,sizeof(t_client_d2cs_gameinforeq),MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } if (!(game=d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_error,__FUNCTION__,"game %s not found",gamename); return 0; } seqno=bn_short_get(packet->u.client_d2cs_gameinforeq.seqno); if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gameinforeply)); packet_set_type(rpacket,D2CS_CLIENT_GAMEINFOREPLY); bn_short_set(&rpacket->u.d2cs_client_gameinforeply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gameinforeply.gameflag,game_get_gameflag(game)); bn_int_set(&rpacket->u.d2cs_client_gameinforeply.etime,std::time(NULL)-d2cs_game_get_create_time(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.charlevel,game_get_charlevel(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.leveldiff,game_get_leveldiff(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.maxchar,game_get_maxchar(game)); packet_append_string(rpacket, game_get_desc(game) ? game_get_desc(game) : NULL); n=0; BEGIN_LIST_TRAVERSE_DATA_CONST(game_get_charlist(game),info,t_game_charinfo) { if (!info->charname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname in game %s char list",gamename); continue; } packet_append_string(rpacket,info->charname); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.chclass[n],info->chclass); /* GUI is limited to a max level of 255 */ if (info->level < 255) { bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n],info->level); } else { bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n], 255); } n++; } END_LIST_TRAVERSE_DATA_CONST() bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.currchar,n); if (n!=game_get_currchar(game)) { eventlog(eventlog_level_error,__FUNCTION__,"game %s character list corrupted",gamename); } conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); }
static int d2charinfo_init(t_d2charinfo_file * chardata, char const * account, char const * charname, unsigned char classs, unsigned short status) { unsigned int i; time_t now; now=time(NULL); bn_int_set(&chardata->header.magicword,D2CHARINFO_MAGICWORD); bn_int_set(&chardata->header.version,D2CHARINFO_VERSION); bn_int_set(&chardata->header.create_time,now); bn_int_set(&chardata->header.last_time,now); bn_int_set(&chardata->header.total_play_time,0); memset(chardata->header.charname, 0,MAX_CHARNAME_LEN); strncpy(chardata->header.charname,charname,MAX_CHARNAME_LEN); memset(chardata->header.account, 0,MAX_ACCTNAME_LEN); strncpy(chardata->header.account,account,MAX_ACCTNAME_LEN); memset(chardata->header.realmname, 0,MAX_REALMNAME_LEN); strncpy(chardata->header.realmname,prefs_get_realmname(),MAX_REALMNAME_LEN); bn_int_set(&chardata->header.checksum,0); for (i=0; i<NELEMS(chardata->header.reserved); i++) { bn_int_set(&chardata->header.reserved[i],0); } bn_int_set(&chardata->summary.charlevel,1); bn_int_set(&chardata->summary.experience,0); bn_int_set(&chardata->summary.charclass,classs); bn_int_set(&chardata->summary.charstatus,status); memset(chardata->portrait.gfx,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.gfx)); memset(chardata->portrait.color,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.color)); memset(chardata->portrait.u2,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.u2)); memset(chardata->portrait.u1,D2CHARINFO_PORTRAIT_MASK,sizeof(chardata->portrait.u1)); memset(chardata->pad,0,sizeof(chardata->pad)); bn_short_set(&chardata->portrait.header,D2CHARINFO_PORTRAIT_HEADER); bn_byte_set(&chardata->portrait.status,status|D2CHARINFO_PORTRAIT_MASK); bn_byte_set(&chardata->portrait.classs,classs+1); bn_byte_set(&chardata->portrait.level,1); if (charstatus_get_ladder(status)) bn_byte_set(&chardata->portrait.ladder, 1); else bn_byte_set(&chardata->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); bn_byte_set(&chardata->portrait.end,'\0'); memset(chardata->pad,0,sizeof(chardata->pad)); return 0; }
static int _client_anongame_cancel(t_connection * c) { t_packet * rpacket; t_connection * tc[ANONGAME_MAX_GAMECOUNT / 2]; // [quetzal] 20020809 - added a_count, so we dont refer to already destroyed anongame t_anongame *a = conn_get_anongame(c); int a_count, i; eventlog(eventlog_level_info, __FUNCTION__, "[%d] got FINDANONGAME CANCEL packet", conn_get_socket(c)); if (!a) return -1; a_count = anongame_get_count(a); // anongame_unqueue(c, anongame_get_queue(a)); // -- already doing unqueue in conn_destroy_anongame for (i = 0; i < ANONGAME_MAX_GAMECOUNT / 2; i++) tc[i] = anongame_get_tc(a, i); for (i = 0; i < ANONGAME_MAX_GAMECOUNT / 2; i++) { if (tc[i] == NULL) continue; conn_set_routeconn(tc[i], NULL); conn_destroy_anongame(tc[i]); } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_findanongame_playgame_cancel)); packet_set_type(rpacket, SERVER_FINDANONGAME_PLAYGAME_CANCEL); bn_byte_set(&rpacket->u.server_findanongame_playgame_cancel.cancel, SERVER_FINDANONGAME_CANCEL); bn_int_set(&rpacket->u.server_findanongame_playgame_cancel.count, a_count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; }
int on_bnetd_gameinforeq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_game * game; char const * gamename; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(gamename = packet_get_str_const(packet,sizeof(t_bnetd_d2cs_gameinforeq),MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename"); return -1; } if (!(game = d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_error,__FUNCTION__,"request for unknown game \"%s\"",gamename); return -1; } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket, sizeof(t_d2cs_bnetd_gameinforeply)); packet_set_type(rpacket, D2CS_BNETD_GAMEINFOREPLY); bn_int_set(&rpacket->u.d2cs_bnetd_gameinforeply.h.seqno,0); packet_append_string(rpacket, gamename); bn_byte_set(&rpacket->u.d2cs_bnetd_gameinforeply.difficulty, game_get_gameflag_difficulty(game)); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; }
/* tournament notice disabled at this time, but responce is sent to cleint */ static int _client_anongame_tournament(t_connection * c, t_packet const * const packet) { t_packet * rpacket; t_account * account = conn_get_account(c); t_clienttag clienttag = conn_get_clienttag(c); unsigned int start_prelim = tournament_get_start_preliminary(); unsigned int end_signup = tournament_get_end_signup(); unsigned int end_prelim = tournament_get_end_preliminary(); unsigned int start_r1 = tournament_get_start_round_1(); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_anongame_tournament_reply)); packet_set_type(rpacket, SERVER_FINDANONGAME_TOURNAMENT_REPLY); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.option, 7); bn_int_set(&rpacket->u.server_anongame_tournament_reply.count, bn_int_get(packet->u.client_anongame_tournament_request.count)); if (!start_prelim || (end_signup <= now && tournament_user_signed_up(account) < 0) || tournament_check_client(clienttag) < 0) { /* No Tournament Notice */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (start_prelim >= now) { /* Tournament Notice */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 1); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_prelim)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_prelim - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x00); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (end_signup >= now) { /* Tournament Signup Notice - Play Game Active */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_signup)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, end_signup - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (end_prelim >= now) { /* Tournament Prelim Period - Play Game Active */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 3); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_prelim)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, end_prelim - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (start_r1 >= now && (tournament_get_game_in_progress())) { /* Prelim Period Over - Shows user stats (not all prelim games finished) */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 4); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_r1 - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); /* 00 00 */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (!(tournament_get_in_finals_status(account))) { /* Prelim Period Over - user did not make finals - Shows user stats */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 5); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } /* cycle through [type-6] & [type-7] packets * * use [type-6] to show client "eliminated" or "continue" * timestamp , countdown & round number (of next round) must be set if clinet continues * * use [type-7] to make cleint wait for 44FF packet option 1 to start game (A guess, not tested) * * not sure if there is overall winner packet sent at end of last final round */ // UNDONE: next two conditions never executed else if ((0)) { /* User in finals - Shows user stats and start of next round*/ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 6); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_r1 - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0x0000); /* 00 00 */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 4); /* round number */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); /* 0 = continue , 1= eliminated */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of rounds in finals */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if ((0)) { /* user waiting for match to be made */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 7); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 1); /* round number */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of finals */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; }
static int _client_anongame_infos(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (bn_int_get(packet->u.client_findanongame_inforeq.count) > 1) { /* reply with 0 entries found */ int temp = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, 0); packet_append_data(rpacket, &temp, 1); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } else { int i; int client_tag; int server_tag_count = 0; int client_tag_unk; int server_tag_unk; bn_int temp; char noitems; char * tmpdata; int tmplen; t_clienttag clienttag = conn_get_clienttag(c); char last_packet = 0x00; char other_packet = 0x01; char langstr[5]; t_gamelang gamelang = conn_get_gamelang(c); bn_int_tag_get((bn_int const *)&gamelang, langstr, 5); /* Send seperate packet for each item requested * sending all at once overloaded w3xp * [Omega] */ for (i = 0; i < bn_byte_get(packet->u.client_findanongame_inforeq.noitems); i++){ noitems = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } /* Starting the packet stuff */ packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, 1); std::memcpy(&temp, (packet_get_data_const(packet, 10 + (i * 8), 4)), sizeof(int)); client_tag = bn_int_get(temp); std::memcpy(&temp, packet_get_data_const(packet, 14 + (i * 8), 4), sizeof(int)); client_tag_unk = bn_int_get(temp); switch (client_tag){ case CLIENT_FINDANONGAME_INFOTAG_URL: bn_int_set((bn_int*)&server_tag_unk, 0xBF1F1047); packet_append_data(rpacket, "LRU\0", 4); packet_append_data(rpacket, &server_tag_unk, 4); // FIXME: Maybe need do do some checks to avoid prefs empty strings. tmpdata = anongame_infos_data_get_url(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_URL", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_MAP: bn_int_set((bn_int*)&server_tag_unk, 0x70E2E0D5); packet_append_data(rpacket, "PAM\0", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_map(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_MAP", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_TYPE: bn_int_set((bn_int*)&server_tag_unk, 0x7C87DEEE); packet_append_data(rpacket, "EPYT", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_type(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_TYPE", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_DESC: bn_int_set((bn_int*)&server_tag_unk, 0xA4F0A22F); packet_append_data(rpacket, "CSED", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_desc(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_DESC", client_tag_unk); noitems++; server_tag_count++; break; case CLIENT_FINDANONGAME_INFOTAG_LADR: bn_int_set((bn_int*)&server_tag_unk, 0x3BADE25A); packet_append_data(rpacket, "RDAL", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_ladr(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_LADR", client_tag_unk); break; default: eventlog(eventlog_level_debug, __FUNCTION__, "unrec client_tag request tagid=(0x%01x) tag=(0x%04x)", i, client_tag); } //Adding a last padding null-byte if (server_tag_count == bn_byte_get(packet->u.client_findanongame_inforeq.noitems)) packet_append_data(rpacket, &last_packet, 1); /* only last packet in group gets 0x00 */ else packet_append_data(rpacket, &other_packet, 1); /* the rest get 0x01 */ //Go,go,go bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, noitems); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; }
/* Open portrait in Warcraft 3 user profile */ static int _client_anongame_get_icon(t_connection * c, t_packet const * const packet) { t_packet * rpacket; //BlacKDicK 04/20/2003 Need some huge re-work on this. { struct { char icon_code[4]; unsigned int portrait_code; char race; bn_short required_wins; char client_enabled; } tempicon; //FIXME: Add those to the prefs and also merge them on accoun_wrap; // FIXED BY DJP 07/16/2003 FOR 110 CHANGE ( TOURNEY & RACE WINS ) + Table_witdh short icon_req_race_wins; short icon_req_tourney_wins; int race[] = { W3_RACE_RANDOM, W3_RACE_HUMANS, W3_RACE_ORCS, W3_RACE_UNDEAD, W3_RACE_NIGHTELVES, W3_RACE_DEMONS }; char race_char[6] = { 'R', 'H', 'O', 'U', 'N', 'D' }; char icon_pos[5] = { '2', '3', '4', '5', '6', }; char table_width = 6; char table_height = 5; int i, j; char rico; unsigned int rlvl, rwins; t_clienttag clienttag; t_account * acc; char user_icon[5]; char const * uicon; clienttag = conn_get_clienttag(c); acc = conn_get_account(c); /* WAR3 uses a different table size, might change if blizzard add tournament support to RoC */ if (clienttag == CLIENTTAG_WARCRAFT3_UINT) { table_width = 5; table_height = 4; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] got FINDANONGAME Get Icons packet", conn_get_socket(c)); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_findanongame_iconreply)); packet_set_type(rpacket, SERVER_FINDANONGAME_ICONREPLY); bn_int_set(&rpacket->u.server_findanongame_iconreply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_iconreply.option, CLIENT_FINDANONGAME_GET_ICON); if (prefs_get_custom_icons() == 1) { // get current custom icon t_icon_info * icon; if (icon = customicons_get_icon_by_account(acc, clienttag)) std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, icon->icon_code, 4); } else if ((uicon = account_get_user_icon(acc, clienttag))) { std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, uicon, 4); } else { account_get_raceicon(acc, &rico, &rlvl, &rwins, clienttag); std::sprintf(user_icon, "%1d%c3W", rlvl, rico); std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, user_icon, 4); } bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_width, table_width); bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_size, table_width*table_height); for (j = 0; j < table_height; j++){ icon_req_race_wins = anongame_infos_get_ICON_REQ(j + 1, clienttag); for (i = 0; i < table_width; i++){ tempicon.race = i; tempicon.icon_code[0] = icon_pos[j]; tempicon.icon_code[1] = race_char[i]; tempicon.icon_code[2] = '3'; tempicon.icon_code[3] = 'W'; tempicon.portrait_code = (account_icon_to_profile_icon(tempicon.icon_code, acc, clienttag)); if (i <= 4){ //Building the icon for the races bn_short_set(&tempicon.required_wins, icon_req_race_wins); if (account_get_racewins(acc, race[i], clienttag) >= icon_req_race_wins) { if (prefs_get_custom_icons() == 1) tempicon.client_enabled = 0; else tempicon.client_enabled = 1; } else{ tempicon.client_enabled = 0; } } else{ //Building the icon for the tourney icon_req_tourney_wins = anongame_infos_get_ICON_REQ_TOURNEY(j + 1); bn_short_set(&tempicon.required_wins, icon_req_tourney_wins); if (account_get_racewins(acc, race[i], clienttag) >= icon_req_tourney_wins) { if (prefs_get_custom_icons() == 1) tempicon.client_enabled = 0; else tempicon.client_enabled = 1; } else{ tempicon.client_enabled = 0; } } packet_append_data(rpacket, &tempicon, sizeof(tempicon)); } } //Go,go,go conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; }
extern char const * character_get_playerinfo(t_character const * ch) { t_d2char_info d2char_info; static char playerinfo[sizeof(t_d2char_info)+4]; if (!ch) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL character"); return NULL; } /* ff 0f 68 00 ..h. 0x0040: 01 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 ................ 0x0050: d8 94 f6 08 b1 65 77 02 65 76 69 6c 67 72 75 73 .....ew.evilgrus 0x0060: 73 6c 65 72 00 56 44 32 44 42 65 74 61 57 65 73 sler.VD2DBetaWes 0x0070: 74 2c 74 61 72 61 6e 2c 83 80 ff ff ff ff ff 2f t,taran,......./ 0x0080: ff ff ff ff ff ff ff ff ff ff 03 ff ff ff ff ff ................ 0x0090: ff ff ff ff ff ff ff ff ff ff ff 07 80 80 80 80 ................ 0x00a0: ff ff ff 00 */ bn_byte_set(&d2char_info.unknownb1,ch->unknownb1); bn_byte_set(&d2char_info.unknownb2,ch->unknownb2); bn_byte_set(&d2char_info.helmgfx,ch->helmgfx); bn_byte_set(&d2char_info.bodygfx,ch->bodygfx); bn_byte_set(&d2char_info.leggfx,ch->leggfx); bn_byte_set(&d2char_info.lhandweapon,ch->lhandweapon); bn_byte_set(&d2char_info.lhandgfx,ch->lhandgfx); bn_byte_set(&d2char_info.rhandweapon,ch->rhandweapon); bn_byte_set(&d2char_info.rhandgfx,ch->rhandgfx); bn_byte_set(&d2char_info.unknownb3,ch->unknownb3); bn_byte_set(&d2char_info.unknownb4,ch->unknownb4); bn_byte_set(&d2char_info.unknownb5,ch->unknownb5); bn_byte_set(&d2char_info.unknownb6,ch->unknownb6); bn_byte_set(&d2char_info.unknownb7,ch->unknownb7); bn_byte_set(&d2char_info.unknownb8,ch->unknownb8); bn_byte_set(&d2char_info.unknownb9,ch->unknownb9); bn_byte_set(&d2char_info.unknownb10,ch->unknownb10); bn_byte_set(&d2char_info.unknownb11,ch->unknownb11); bn_byte_set(&d2char_info.chclass,ch->chclass); bn_int_set(&d2char_info.unknown1,ch->unknown1); bn_int_set(&d2char_info.unknown2,ch->unknown2); bn_int_set(&d2char_info.unknown3,ch->unknown3); bn_int_set(&d2char_info.unknown4,ch->unknown4); bn_byte_set(&d2char_info.level,ch->level); bn_byte_set(&d2char_info.status,ch->status); bn_byte_set(&d2char_info.title,ch->title); bn_byte_set(&d2char_info.unknownb13,ch->unknownb13); bn_byte_set(&d2char_info.emblembgc,ch->emblembgc); bn_byte_set(&d2char_info.emblemfgc,ch->emblemfgc); bn_byte_set(&d2char_info.emblemnum,ch->emblemnum); bn_byte_set(&d2char_info.unknownb14,ch->unknownb14); std::memcpy(playerinfo,&d2char_info,sizeof(d2char_info)); std::strcpy(&playerinfo[sizeof(d2char_info)],ch->guildname); return playerinfo; }
extern int tracker_send_report(t_addrlist const * laddrs) { t_addr const * addrl; t_elem const * currl; t_addr const * addrt; t_elem const * currt; t_trackpacket packet; struct utsname utsbuf; struct sockaddr_in tempaddr; t_laddr_info * laddr_info; char tempa[64]; char tempb[64]; if (addrlist_get_length(track_servers)>0) { std::memset(&packet,0,sizeof(packet)); bn_short_nset(&packet.packet_version,(unsigned short)TRACK_VERSION); /* packet.port is set below */ bn_int_nset(&packet.flags, 0); std::strncpy((char *)packet.server_location, prefs_get_location(), sizeof(packet.server_location)); bn_byte_set(&packet.server_location[sizeof(packet.server_location)-1],'\0'); std::strncpy((char *)packet.software, PVPGN_SOFTWARE, sizeof(packet.software)); bn_byte_set(&packet.software[sizeof(packet.software)-1],'\0'); std::strncpy((char *)packet.version, PVPGN_VERSION, sizeof(packet.version)); bn_byte_set(&packet.version[sizeof(packet.version)-1],'\0'); std::strncpy((char *)packet.server_desc, prefs_get_description(), sizeof(packet.server_desc)); bn_byte_set(&packet.server_desc[sizeof(packet.server_desc)-1],'\0'); std::strncpy((char *)packet.server_url, prefs_get_url(), sizeof(packet.server_url)); bn_byte_set(&packet.server_url[sizeof(packet.server_url)-1],'\0'); std::strncpy((char *)packet.contact_name, prefs_get_contact_name(), sizeof(packet.contact_name)); bn_byte_set(&packet.contact_name[sizeof(packet.contact_name)-1],'\0'); std::strncpy((char *)packet.contact_email, prefs_get_contact_email(), sizeof(packet.contact_email)); bn_byte_set(&packet.contact_email[sizeof(packet.contact_email)-1],'\0'); bn_int_nset(&packet.users,connlist_login_get_length()); bn_int_nset(&packet.channels,channellist_get_length()); bn_int_nset(&packet.games,gamelist_get_length()); bn_int_nset(&packet.uptime,server_get_uptime()); bn_int_nset(&packet.total_logins,connlist_total_logins()); bn_int_nset(&packet.total_games,gamelist_total_games()); if (uname(&utsbuf)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"could not get platform info (uname: %s)",pstrerror(errno)); std::strncpy((char *)packet.platform,"",sizeof(packet.platform)); } else { std::strncpy((char *)packet.platform, utsbuf.sysname, sizeof(packet.platform)); bn_byte_set(&packet.platform[sizeof(packet.platform)-1],'\0'); } LIST_TRAVERSE_CONST(laddrs,currl) { addrl = (t_addr*)elem_get_data(currl); if (!(laddr_info = (t_laddr_info*)addr_get_data(addrl).p)) { eventlog(eventlog_level_error,__FUNCTION__,"address data is NULL"); continue; } if (laddr_info->type!=laddr_type_bnet) continue; /* don't report IRC, telnet, and other non-game ports */ bn_short_nset(&packet.port,addr_get_port(addrl)); LIST_TRAVERSE_CONST(track_servers,currt) { addrt = (t_addr*)elem_get_data(currt); std::memset(&tempaddr,0,sizeof(tempaddr)); tempaddr.sin_family = PSOCK_AF_INET; tempaddr.sin_port = htons(addr_get_port(addrt)); tempaddr.sin_addr.s_addr = htonl(addr_get_ip(addrt)); if (!addr_get_addr_str(addrl,tempa,sizeof(tempa))) std::strcpy(tempa,"x.x.x.x:x"); if (!addr_get_addr_str(addrt,tempb,sizeof(tempb))) std::strcpy(tempa,"x.x.x.x:x"); /* eventlog(eventlog_level_debug,__FUNCTION__,"sending tracking info from %s to %s",tempa,tempb); */ if (psock_sendto(laddr_info->usocket,&packet,sizeof(packet),0,(struct sockaddr *)&tempaddr,(psock_t_socklen)sizeof(tempaddr))<0) eventlog(eventlog_level_warn,__FUNCTION__,"could not send tracking information from %s to %s (psock_sendto: %s)",tempa,tempb,pstrerror(errno)); }
extern int packet_set_type(t_packet * packet, unsigned int type) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } switch (packet->pclass) { case packet_class_init: if (type!=CLIENT_INITCONN) { eventlog(eventlog_level_error,__FUNCTION__,"init packet type 0x%08x is not valid",type); return -1; } return 0; case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"bnet packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } if (type>MAX_NORMAL_TYPE) { eventlog(eventlog_level_error,__FUNCTION__,"bnet packet type 0x%08x is too large",type); return -1; } bn_short_set(&packet->u.bnet.h.type,(unsigned short)type); return 0; case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"file packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } if (type>MAX_FILE_TYPE) { eventlog(eventlog_level_error,__FUNCTION__,"file packet type 0x%08x is too large",type); return -1; } bn_short_set(&packet->u.file.h.type,(unsigned short)type); return 0; case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"udp packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_int_set(&packet->u.udp.h.type,type); return 0; case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2game packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_byte_set(&packet->u.d2game.h.type,type); return 0; case packet_class_d2gs: if (packet_get_size(packet)<sizeof(t_d2cs_d2gs_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2gs packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_short_set(&packet->u.d2cs_d2gs.h.type,type); return 0; case packet_class_d2cs_bnetd: if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs_bnetd packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_short_set(&packet->u.d2cs_bnetd.h.type,type); return 0; case packet_class_d2cs: if (packet_get_size(packet)<sizeof(t_d2cs_client_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_byte_set(&packet->u.d2cs_client.h.type,type); return 0; case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"w3route packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_short_set(&packet->u.w3route.h.type,(unsigned short)type); return 0; case packet_class_wolgameres: eventlog(eventlog_level_error,__FUNCTION__,"can not set packet type for wol gameres packet"); return 0; case packet_class_raw: eventlog(eventlog_level_error,__FUNCTION__,"can not set packet type for raw packet"); return 0; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return -1; } }
static int on_client_gamelistreq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_game * game; unsigned int count; unsigned int seqno; std::time_t now; unsigned int maxlifetime; t_elem const * start_elem; t_elem const * elem; seqno=bn_short_get(packet->u.client_d2cs_gamelistreq.seqno); /* if (seqno%2) return 0; */ count=0; now=std::time(NULL); maxlifetime=prefs_get_game_maxlifetime(); elem=start_elem=gamelist_get_curr_elem(); if (!elem) elem=list_get_first_const(d2cs_gamelist()); else elem=elem_get_next_const(d2cs_gamelist(),elem); for (; elem != start_elem; elem=elem_get_next_const(d2cs_gamelist(),elem)) { if (!elem) { elem=list_get_first_const(d2cs_gamelist()); if (elem == start_elem) break; } if (!(game=(t_game*)elem_get_data(elem))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); break; } if (maxlifetime && (now-game->create_time>maxlifetime)) continue; if (!game_get_currchar(game)) continue; if (!prefs_allow_gamelist_showall()) { if (conn_get_charinfo_difficulty(c)!=game_get_gameflag_difficulty(game)) continue; } if (prefs_hide_pass_games()) if (d2cs_game_get_pass(game)) continue; if (d2cs_try_joingame(c,game,"")!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) continue; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply)); packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY); bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,d2cs_game_get_id(game)); bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,game_get_currchar(game)); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,game_get_gameflag(game)); packet_append_string(rpacket,d2cs_game_get_name(game)); packet_append_string(rpacket,game_get_desc(game)); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); count++; if (prefs_get_maxgamelist() && count>=prefs_get_maxgamelist()) break; } } gamelist_set_curr_elem(elem); if (count) { if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply)); packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY); bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,0); bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,0); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,0); packet_append_string(rpacket,""); packet_append_string(rpacket,""); packet_append_string(rpacket,""); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } return 0; }
static int on_client_creategamereq(t_connection * c, t_packet * packet) { char const * gamename; char const * gamepass; char const * gamedesc; t_game * game; t_d2gs * gs; t_gq * gq; unsigned int tempflag,gameflag; unsigned int leveldiff, maxchar, difficulty, expansion, hardcore, ladder; unsigned int seqno, reply; unsigned int pos; t_elem * elem; pos=sizeof(t_client_d2cs_creategamereq); if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } pos+=std::strlen(gamename)+1; if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass"); return -1; } pos+=std::strlen(gamepass)+1; if (!(gamedesc=packet_get_str_const(packet,pos,MAX_GAMEDESC_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game desc"); return -1; } tempflag=bn_int_get(packet->u.client_d2cs_creategamereq.gameflag); leveldiff=bn_byte_get(packet->u.client_d2cs_creategamereq.leveldiff); maxchar=bn_byte_get(packet->u.client_d2cs_creategamereq.maxchar); difficulty=gameflag_get_difficulty(tempflag); if (difficulty > conn_get_charinfo_difficulty(c)) { eventlog(eventlog_level_error,__FUNCTION__,"game difficulty exceed character limit %d %d",difficulty, conn_get_charinfo_difficulty(c)); return 0; } expansion=conn_get_charinfo_expansion(c); hardcore=conn_get_charinfo_hardcore(c); ladder=conn_get_charinfo_ladder(c); gameflag=gameflag_create(ladder,expansion,hardcore,difficulty); gs = NULL; game = NULL; gq=conn_get_gamequeue(c); if (d2cs_gamelist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in gamelist",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!gq && gqlist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in game queue",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!(gs=d2gslist_choose_server())) { if (gq) { eventlog(eventlog_level_error,__FUNCTION__,"client %d is already in game queue",d2cs_conn_get_sessionnum(c)); conn_set_gamequeue(c,NULL); gq_destroy(gq,&elem); return 0; } else if ((gq=gq_create(d2cs_conn_get_sessionnum(c), packet, gamename))) { conn_set_gamequeue(c,gq); d2cs_send_client_creategamewait(c,gqlist_get_length()); return 0; } reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (hardcore && conn_get_charinfo_dead(c)) { reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (!(game=d2cs_game_create(gamename,gamepass,gamedesc,gameflag))) { reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else { reply=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED; game_set_d2gs(game,gs); d2gs_add_gamenum(gs, 1); game_set_gameflag_ladder(game,ladder); game_set_gameflag_expansion(game,expansion); game_set_created(game,0); game_set_leveldiff(game,leveldiff); game_set_charlevel(game,conn_get_charinfo_level(c)); game_set_maxchar(game,maxchar); game_set_gameflag_difficulty(game,difficulty); game_set_gameflag_hardcore(game,hardcore); } seqno=bn_short_get(packet->u.client_d2cs_creategamereq.seqno); if (reply!=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_creategamereply)); packet_set_type(rpacket,D2CS_CLIENT_CREATEGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_creategamereply.seqno,seqno); bn_short_set(&rpacket->u.d2cs_client_creategamereply.u1,0); bn_short_set(&rpacket->u.d2cs_client_creategamereply.gameid,0); bn_int_set(&rpacket->u.d2cs_client_creategamereply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } else { t_packet * gspacket; t_sq * sq; struct in_addr addr; if ((gspacket=packet_create(packet_class_d2gs))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) { packet_set_size(gspacket,sizeof(t_d2cs_d2gs_creategamereq)); packet_set_type(gspacket,D2CS_D2GS_CREATEGAMEREQ); bn_int_set(&gspacket->u.d2cs_d2gs_creategamereq.h.seqno,sq_get_seqno(sq)); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.difficulty,difficulty); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.hardcore,hardcore); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.expansion,expansion); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.ladder,ladder); packet_append_string(gspacket,gamename); packet_append_string(gspacket,gamepass); packet_append_string(gspacket,gamedesc); packet_append_string(gspacket,d2cs_conn_get_account(c)); packet_append_string(gspacket,d2cs_conn_get_charname(c)); addr.s_addr = htonl(d2cs_conn_get_addr(c)); packet_append_string(gspacket,inet_ntoa(addr)); conn_push_outqueue(d2gs_get_connection(gs),gspacket); } packet_del_ref(gspacket); eventlog(eventlog_level_info,__FUNCTION__,"request create game %s on gs %d",gamename,d2gs_get_id(gs)); } } return 0; }
extern int d2ladder_saveladder(void) { t_d2ladderfile_ladderindex lhead[D2LADDER_MAXTYPE]; t_d2ladderfile_header fileheader; std::FILE * fdladder; int start; unsigned int i,j, number; t_d2ladder * d2ladder; t_d2ladderfile_ladderinfo * ldata; char * XMLfilename; std::FILE * XMLfile; /* if(!d2ladder_change_count) { eventlog(eventlog_level_debug,__FUNCTION__,"ladder data unchanged, skip saving"); return 0; } */ start=sizeof(fileheader)+sizeof(lhead); for(i=0;i<D2LADDER_MAXTYPE;i++) { d2ladder=d2ladderlist_find_type(i); bn_int_set(&lhead[i].type,d2ladder->type); bn_int_set(&lhead[i].offset,start); bn_int_set(&lhead[i].number,d2ladder->len); start+=d2ladder->len*sizeof(*ldata); } if (!d2ladder_ladder_file) return -1; if (!d2ladder_backup_file) return -1; if(d2ladder_checksum_check()==1) { eventlog(eventlog_level_info,__FUNCTION__,"backup ladder file"); if (p_rename(d2ladder_ladder_file,d2ladder_backup_file)==-1) { eventlog(eventlog_level_warn,__FUNCTION__,"error std::rename %s to %s", d2ladder_ladder_file, d2ladder_backup_file); } } fdladder=std::fopen(d2ladder_ladder_file,"wb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file); return -1; } // aaron: add extra output for XML ladder here ---> if (d2dbs_prefs_get_XML_output_ladder()) { XMLfilename = (char*)xmalloc(std::strlen(d2dbs_prefs_get_ladder_dir())+1+std::strlen(XMLname)+1); std::sprintf(XMLfilename,"%s/%s",d2dbs_prefs_get_ladder_dir(),XMLname); if (!(XMLfile = std::fopen(XMLfilename,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open XML ladder file for output"); } else { d2ladder_print_XML(XMLfile); std::fclose(XMLfile); xfree(XMLfilename); } } // <--- bn_int_set(&fileheader.maxtype,d2ladder_maxtype); bn_int_set(&fileheader.checksum,0); std::fwrite(&fileheader,1,sizeof(fileheader),fdladder); std::fwrite(lhead,1,sizeof(lhead),fdladder); for(i=0;i<d2ladder_maxtype;i++) { number=bn_int_get(lhead[i].number); if(number<=0) continue; d2ladder=d2ladderlist_find_type(i); ldata=(t_d2ladderfile_ladderinfo*)xmalloc(number * sizeof(*ldata)); std::memset(ldata,0,number * sizeof(*ldata)); for (j=0; j< number; j++) { bn_int_set(&ldata[j].experience,d2ladder->info[j].experience); bn_short_set(&ldata[j].status, d2ladder->info[j].status); bn_byte_set(&ldata[j].level, d2ladder->info[j].level); bn_byte_set(&ldata[j].chclass, d2ladder->info[j].chclass); std::strncpy(ldata[j].charname,d2ladder->info[j].charname,sizeof(ldata[j].charname)); } std::fwrite(ldata,1,number*sizeof(*ldata),fdladder); xfree(ldata); } std::fclose(fdladder); d2ladder_checksum_set(); eventlog(eventlog_level_info,__FUNCTION__,"ladder file saved (%d changes)",d2ladder_change_count); d2ladder_change_count=0; return 0; }
extern int d2charinfo_load(char const * account, char const * charname, t_d2charinfo_file * data) { char * file; int size, ladder_time; if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); size=sizeof(t_d2charinfo_file); if (file_read(file,data,&size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading character file %s",file); xfree(file); return -1; } if (size!=sizeof(t_d2charinfo_file)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad charinfo file %s (length %d)",charname,size); xfree(file); return -1; } d2char_portrait_init(&data->portrait); if (d2charinfo_check(data) < 0) { xfree(file); return -1; } if (!(charstatus_get_ladder(bn_int_get(data->summary.charstatus)))) { bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); xfree(file); return 0; } ladder_time = prefs_get_ladder_start_time(); if ((ladder_time > 0) && bn_int_get(data->header.create_time) < ladder_time) { char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; unsigned int size; unsigned int version; unsigned int checksum; FILE * fp; eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) was created in old ladder season, set to non-ladder", charname, account); if (!(fp=fopen(file,"wb"))) { eventlog(eventlog_level_error,__FUNCTION__,"charinfo file \"%s\" does not exist for account \"%s\"",file,account); xfree(file); return 0; } xfree(file); charstatus = bn_int_get(data->summary.charstatus); charstatus_set_ladder(charstatus, 0); bn_int_set(&data->summary.charstatus, charstatus); status=bn_byte_get(data->portrait.status); charstatus_set_ladder(status,0); bn_byte_set(&data->portrait.status,status); bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); if (fwrite(data,1,sizeof(*data),fp)!=sizeof(*data)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return 0; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x5C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_ladder(status,0); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ bn_byte_set((bn_byte *)(buffer+status_offset),status); if (version>=0x5C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); } fseek(fp,0,SEEK_SET); if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); } else { bn_byte_set(&data->portrait.ladder, 1); xfree(file); } return 0; }
extern int d2char_convert(char const * account, char const * charname) { FILE * fp; char * file; unsigned char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; t_d2charinfo_file charinfo; unsigned int size; unsigned int version; unsigned int checksum; ASSERT(account,-1); ASSERT(charname,-1); /* Playing with a expanstion char on a classic realm will cause the game server to crash, therefore I recommed setting allow_convert = 0 in the d2cs.conf We need to do this to prevent creating classic char and converting to expantion on a classic realm. LOD Char must be created on LOD realm */ if (!prefs_get_allow_convert()) { eventlog(eventlog_level_info,__FUNCTION__,"Convert char has been disabled"); return -1; } /* Procedure is stopped here and returned if allow_convet = 0 in d2cs.conf */ if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open charinfo file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); if (fread(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charinfo file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } charstatus=bn_int_get(charinfo.summary.charstatus); charstatus_set_expansion(charstatus,1); bn_int_set(&charinfo.summary.charstatus,charstatus); status=bn_byte_get(charinfo.portrait.status); charstatus_set_expansion(status,1); bn_byte_set(&charinfo.portrait.status,status); fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charinfo file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x0000005C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_expansion(status,1); bn_byte_set((bn_byte *)(buffer+status_offset),status); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ if (version>=0x0000005C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ } fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charsave file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) converted to expansion",charname,account); return 0; }