diff options
Diffstat (limited to 'src/char/char.c')
-rw-r--r-- | src/char/char.c | 600 |
1 files changed, 309 insertions, 291 deletions
diff --git a/src/char/char.c b/src/char/char.c index 625becef8..ccf19cad9 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -111,16 +111,6 @@ struct char_session_data { time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) }; -#define AUTH_FIFO_SIZE 256 -struct { - int account_id, char_id, login_id1, login_id2; - uint32 ip; - int delflag; - int sex; - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) -} auth_fifo[AUTH_FIFO_SIZE]; -int auth_fifo_pos = 0; - int char_id_count = START_CHAR_NUM; struct character_data *char_dat; @@ -160,7 +150,29 @@ int online_gm_display_min_level = 20; // minimum GM level to display 'GM' when w //These are used to aid the map server in identifying valid clients. [Skotlex] static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CHAR_ID; -//Structure for holding in memory which characters are online on the map servers connected. +int console = 0; + +//----------------------------------------------------- +// Auth database +//----------------------------------------------------- +#define AUTH_TIMEOUT 30000 + +struct auth_node { + int account_id; + int char_id; + uint32 login_id1; + uint32 login_id2; + uint32 ip; + int sex; + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) +}; + +static DBMap* auth_db; // int account_id -> struct auth_node* + +//----------------------------------------------------- +// Online User Database +//----------------------------------------------------- + struct online_char_data { int account_id; int char_id; @@ -169,135 +181,13 @@ struct online_char_data { short server; }; -// Holds all online characters. static DBMap* online_char_db; // int account_id -> struct online_char_data* +static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data); -int console = 0; - -//------------------------------ -// Writing function of logs file -//------------------------------ -int char_log(char *fmt, ...) -{ - if(log_char) - { - FILE *logfp; - va_list ap; - time_t raw_time; - char tmpstr[2048]; - - va_start(ap, fmt); - - logfp = fopen(char_log_filename, "a"); - if (logfp) { - if (fmt[0] == '\0') // jump a line if no message - fprintf(logfp, "\n"); - else { - time(&raw_time); - strftime(tmpstr, 24, "%d-%m-%Y %H:%M:%S", localtime(&raw_time)); - sprintf(tmpstr + 19, ": %s", fmt); - vfprintf(logfp, tmpstr, ap); - } - fclose(logfp); - } - va_end(ap); - } - return 0; -} - -//---------------------------------------------------------------------- -// Determine if an account (id) is a GM account -// and returns its level (or 0 if it isn't a GM account or if not found) -//---------------------------------------------------------------------- -int isGM(int account_id) -{ - int i; - - for(i = 0; i < GM_num; i++) - if (gm_account[i].account_id == account_id) - return gm_account[i].level; - return 0; -} - -//Search character data from the aid/cid givem -struct mmo_charstatus* search_character(int aid, int cid) -{ - int i; - for (i = 0; i < char_num; i++) { - if (char_dat[i].status.char_id == cid && char_dat[i].status.account_id == aid) - return &char_dat[i].status; - } - return NULL; -} - -struct mmo_charstatus* search_character_byname(char* character_name) -{ - int i = search_character_index(character_name); - if (i == -1) return NULL; - return &char_dat[i].status; -} - -//---------------------------------------------- -// Search an character id -// (return character index or -1 (if not found)) -// If exact character name is not found, -// the function checks without case sensitive -// and returns index if only 1 character is found -// and similar to the searched name. -//---------------------------------------------- -int search_character_index(char* character_name) -{ - int i, quantity, index; - - quantity = 0; - index = -1; - for(i = 0; i < char_num; i++) { - // Without case sensitive check (increase the number of similar character names found) - if (stricmp(char_dat[i].status.name, character_name) == 0) { - // Strict comparison (if found, we finish the function immediatly with correct value) - if (strcmp(char_dat[i].status.name, character_name) == 0) - return i; - quantity++; - index = i; - } - } - // Here, the exact character name is not found - // We return the found index of a similar account ONLY if there is 1 similar character - if (quantity == 1) - return index; - - // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found - return -1; -} - -//------------------------------------- -// Return character name with the index -//------------------------------------- -char * search_character_name(int index) -{ - if (index >= 0 && index < char_num) - return char_dat[index].status.name; - - return unknown_char_name; -} - -// Searches if the given character is online, and returns the fd of the -// map-server it is connected to. -int search_character_online(int aid, int cid) +static void* create_online_char_data(DBKey key, va_list args) { - //Look for online character. struct online_char_data* character; - character = (struct online_char_data*)idb_get(online_char_db, aid); - if(character && - character->char_id == cid && - character->server > -1) - return server[character->server].fd; - return -1; -} -static void * create_online_char_data(DBKey key, va_list args) -{ - struct online_char_data* character; - character = (struct online_char_data*)aCalloc(1, sizeof(struct online_char_data)); + CREATE(character, struct online_char_data, 1); character->account_id = key.i; character->char_id = -1; character->server = -1; @@ -306,12 +196,6 @@ static void * create_online_char_data(DBKey key, va_list args) return character; } -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data); - -//------------------------------------------------- -// Set Character online/offline [Wizputer] -//------------------------------------------------- - void set_char_online(int map_id, int char_id, int account_id) { struct online_char_data* character; @@ -328,7 +212,7 @@ void set_char_online(int map_id, int char_id, int account_id) } character = (struct online_char_data*)idb_ensure(online_char_db, account_id, create_online_char_data); - if (online_check && character->char_id != -1 && character->server > -1 && character->server != map_id) + if (online_check && character->char_id != -1 && character->server > -1 && character->server != map_id && map_id != -3) { //char == 99 <- Character logging in, so someone has logged in while one //char is still on map-server, so kick him out, but don't print "error" @@ -339,9 +223,6 @@ void set_char_online(int map_id, int char_id, int account_id) mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); } - character->char_id = (char_id==99)?-1:char_id; - character->server = (char_id==99)?-1:map_id; - if( character->server > -1 ) server[character->server].users++; @@ -349,6 +230,13 @@ void set_char_online(int map_id, int char_id, int account_id) delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); character->waiting_disconnect = -1; } + + //If user is NOT at char screen, delete entry [Kevin] + if(character->char_id != -1) + { + idb_remove(online_char_db, account_id); + } + if (login_fd > 0 && !session[login_fd]->flag.eof) { WFIFOHEAD(login_fd,6); @@ -435,6 +323,116 @@ void set_all_offline(int id) WFIFOSET(login_fd,2); } +//------------------------------ +// Writing function of logs file +//------------------------------ +int char_log(char *fmt, ...) +{ + if(log_char) + { + FILE *logfp; + va_list ap; + time_t raw_time; + char tmpstr[2048]; + + va_start(ap, fmt); + + logfp = fopen(char_log_filename, "a"); + if (logfp) { + if (fmt[0] == '\0') // jump a line if no message + fprintf(logfp, "\n"); + else { + time(&raw_time); + strftime(tmpstr, 24, "%d-%m-%Y %H:%M:%S", localtime(&raw_time)); + sprintf(tmpstr + 19, ": %s", fmt); + vfprintf(logfp, tmpstr, ap); + } + fclose(logfp); + } + va_end(ap); + } + return 0; +} + +//---------------------------------------------------------------------- +// Determine if an account (id) is a GM account +// and returns its level (or 0 if it isn't a GM account or if not found) +//---------------------------------------------------------------------- +int isGM(int account_id) +{ + int i; + + for(i = 0; i < GM_num; i++) + if (gm_account[i].account_id == account_id) + return gm_account[i].level; + return 0; +} + +//Search character data from the aid/cid givem +struct mmo_charstatus* search_character(int aid, int cid) +{ + int i; + for (i = 0; i < char_num; i++) { + if (char_dat[i].status.char_id == cid && char_dat[i].status.account_id == aid) + return &char_dat[i].status; + } + return NULL; +} + +struct mmo_charstatus* search_character_byname(char* character_name) +{ + int i = search_character_index(character_name); + if (i == -1) return NULL; + return &char_dat[i].status; +} + +// Searches if the given character is online, and returns the fd of the +// map-server it is connected to. +int search_character_online(int aid, int cid) +{ + //Look for online character. + struct online_char_data* character; + character = idb_get(online_char_db, aid); + if(character && + character->char_id == cid && + character->server > -1) + return server[character->server].fd; + return -1; +} + +//---------------------------------------------- +// Search an character id +// (return character index or -1 (if not found)) +// If exact character name is not found, +// the function checks without case sensitive +// and returns index if only 1 character is found +// and similar to the searched name. +//---------------------------------------------- +int search_character_index(char* character_name) +{ + int i, quantity, index; + + quantity = 0; + index = -1; + for(i = 0; i < char_num; i++) { + // Without case sensitive check (increase the number of similar character names found) + if (stricmp(char_dat[i].status.name, character_name) == 0) { + // Strict comparison (if found, we finish the function immediatly with correct value) + if (strcmp(char_dat[i].status.name, character_name) == 0) + return i; + quantity++; + index = i; + } + } + // Here, the exact character name is not found + // We return the found index of a similar account ONLY if there is 1 similar character + if (quantity == 1) + return index; + + // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found + return -1; +} + /*--------------------------------------------------- Make a data line for friends list --------------------------------------------------*/ @@ -2066,72 +2064,77 @@ int parse_fromlogin(int fd) RFIFOSKIP(fd,2); break; - case 0x2723: // changesex reply (modified by [Yor]) + // changesex reply + case 0x2723: if (RFIFOREST(fd) < 7) return 0; { - int acc, sex, i, j; + int i, j; unsigned char buf[7]; - acc = RFIFOL(fd,2); - sex = RFIFOB(fd,6); - if (acc > 0) { - for(i = 0; i < AUTH_FIFO_SIZE; i++) { - if (auth_fifo[i].account_id == acc) - auth_fifo[i].sex = sex; - } - for (i = 0; i < char_num; i++) { - if (char_dat[i].status.account_id == acc) { - int jobclass = char_dat[i].status.class_; - char_dat[i].status.sex = sex; - if (jobclass == JOB_BARD || jobclass == JOB_DANCER || - jobclass == JOB_CLOWN || jobclass == JOB_GYPSY || - jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) { - // job modification - if (jobclass == JOB_BARD || jobclass == JOB_DANCER) { - char_dat[i].status.class_ = (sex) ? JOB_BARD : JOB_DANCER; - } else if (jobclass == JOB_CLOWN || jobclass == JOB_GYPSY) { - char_dat[i].status.class_ = (sex) ? JOB_CLOWN : JOB_GYPSY; - } else if (jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) { - char_dat[i].status.class_ = (sex) ? JOB_BABY_BARD : JOB_BABY_DANCER; - } - // remove specifical skills of classes 19, 4020 and 4042 - for(j = 315; j <= 322; j++) { - if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) { - if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv) - char_dat[i].status.skill_point = USHRT_MAX; - else - char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv; - char_dat[i].status.skill[j].id = 0; - char_dat[i].status.skill[j].lv = 0; - } - } - // remove specifical skills of classes 20, 4021 and 4043 - for(j = 323; j <= 330; j++) { - if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) { - if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv) - char_dat[i].status.skill_point = USHRT_MAX; - else - char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv; - - char_dat[i].status.skill[j].id = 0; - char_dat[i].status.skill[j].lv = 0; - } + + int acc = RFIFOL(fd,2); + int sex = RFIFOB(fd,6); + RFIFOSKIP(fd,7); + + if( acc > 0 ) + { + struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); + if( node != NULL ) + node->sex = sex; + + ARR_FIND( 0, char_num, i, char_dat[i].status.account_id == acc ); + if( i < char_num ) + { + int jobclass = char_dat[i].status.class_; + char_dat[i].status.sex = sex; + if (jobclass == JOB_BARD || jobclass == JOB_DANCER || + jobclass == JOB_CLOWN || jobclass == JOB_GYPSY || + jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) { + // job modification + if (jobclass == JOB_BARD || jobclass == JOB_DANCER) { + char_dat[i].status.class_ = (sex) ? JOB_BARD : JOB_DANCER; + } else if (jobclass == JOB_CLOWN || jobclass == JOB_GYPSY) { + char_dat[i].status.class_ = (sex) ? JOB_CLOWN : JOB_GYPSY; + } else if (jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) { + char_dat[i].status.class_ = (sex) ? JOB_BABY_BARD : JOB_BABY_DANCER; + } + // remove specifical skills of classes 19, 4020 and 4042 + for(j = 315; j <= 322; j++) { + if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) { + if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv) + char_dat[i].status.skill_point = USHRT_MAX; + else + char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv; + char_dat[i].status.skill[j].id = 0; + char_dat[i].status.skill[j].lv = 0; } } - // to avoid any problem with equipment and invalid sex, equipment is unequiped. - for (j = 0; j < MAX_INVENTORY; j++) { - if (char_dat[i].status.inventory[j].nameid && char_dat[i].status.inventory[j].equip) - char_dat[i].status.inventory[j].equip = 0; + // remove specifical skills of classes 20, 4021 and 4043 + for(j = 323; j <= 330; j++) { + if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) { + if (char_dat[i].status.skill_point > USHRT_MAX - char_dat[i].status.skill[j].lv) + char_dat[i].status.skill_point = USHRT_MAX; + else + char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv; + + char_dat[i].status.skill[j].id = 0; + char_dat[i].status.skill[j].lv = 0; + } } - char_dat[i].status.weapon = 0; - char_dat[i].status.shield = 0; - char_dat[i].status.head_top = 0; - char_dat[i].status.head_mid = 0; - char_dat[i].status.head_bottom = 0; - - if (char_dat[i].status.guild_id) //If there is a guild, update the guild_member data [Skotlex] - inter_guild_sex_changed(char_dat[i].status.guild_id, acc, char_dat[i].status.char_id, sex); } + // to avoid any problem with equipment and invalid sex, equipment is unequiped. + for (j = 0; j < MAX_INVENTORY; j++) { + if (char_dat[i].status.inventory[j].nameid && char_dat[i].status.inventory[j].equip) + char_dat[i].status.inventory[j].equip = 0; + } + char_dat[i].status.weapon = 0; + char_dat[i].status.shield = 0; + char_dat[i].status.head_top = 0; + char_dat[i].status.head_mid = 0; + char_dat[i].status.head_bottom = 0; + + if (char_dat[i].status.guild_id) //If there is a guild, update the guild_member data [Skotlex] + inter_guild_sex_changed(char_dat[i].status.guild_id, acc, char_dat[i].status.char_id, sex); } // disconnect player if online on char-server disconnect_player(acc); @@ -2140,8 +2143,6 @@ int parse_fromlogin(int fd) WBUFL(buf,2) = acc; WBUFB(buf,6) = sex; mapif_sendall(buf, 7); - - RFIFOSKIP(fd,7); } break; @@ -2318,38 +2319,39 @@ int parse_fromlogin(int fd) } break; - //Login server request to kick a character out. [Skotlex] + // Login server request to kick a character out. [Skotlex] case 0x2734: if (RFIFOREST(fd) < 6) return 0; { - struct online_char_data* character; int aid = RFIFOL(fd,2); - if ((character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL) - { //Kick out this player. - if (character->server > -1) + struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); + RFIFOSKIP(fd,6); + if( character != NULL ) + {// account is already marked as online! + if( character->server > -1 ) { //Kick it from the map server it is on. mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == -1) - character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0); - } else { //Manual kick from char server. + character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0); + } + else + {// Manual kick from char server. struct char_session_data *tsd; int i; - for(i = 0; i < fd_max; i++) { - if (session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid) - { - WFIFOHEAD(i,3); - WFIFOW(i,0) = 0x81; - WFIFOB(i,2) = 2; // "Someone has already logged in with this id" - WFIFOSET(i,3); - break; - } + ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid ); + if( i < fd_max ) + { + WFIFOHEAD(i,3); + WFIFOW(i,0) = 0x81; + WFIFOB(i,2) = 2; // "Someone has already logged in with this id" + WFIFOSET(i,3); + set_eof(i); } - if (i == fd_max) //Shouldn't happen, but just in case. + else //Shouldn't happen, but just in case. set_char_offline(99, aid); } } - RFIFOSKIP(fd,6); } break; @@ -2798,26 +2800,37 @@ int parse_frommap(int fd) break; case 0x2b02: // req char selection - if (RFIFOREST(fd) < 18) + if( RFIFOREST(fd) < 18 ) return 0; + { + struct auth_node* node; + + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + uint32 ip = RFIFOL(fd,14); + RFIFOSKIP(fd,18); + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = account_id; + node->char_id = 0; + node->login_id1 = login_id1; + node->login_id2 = login_id2; + //node->sex = 0; + node->ip = ntohl(ip); + node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) + idb_put(auth_db, account_id, node); + + //Set char to "@ char select" in online db [Kevin] + set_char_online(-3, 99, account_id); - if (auth_fifo_pos >= AUTH_FIFO_SIZE) - auth_fifo_pos = 0; - - auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd,2); - auth_fifo[auth_fifo_pos].char_id = 0; - auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd,6); - auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10); - auth_fifo[auth_fifo_pos].delflag = 2; - auth_fifo[auth_fifo_pos].expiration_time = 0; // unlimited/unknown time by default (not display in map-server) - auth_fifo[auth_fifo_pos].ip = ntohl(RFIFOL(fd,14)); - auth_fifo_pos++; WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = RFIFOL(fd,2); + WFIFOL(fd,2) = account_id; WFIFOB(fd,6) = 0; WFIFOSET(fd,7); - RFIFOSKIP(fd,18); + } break; case 0x2b05: // request "change map server" @@ -3204,7 +3217,7 @@ int parse_char(int fd) { struct online_char_data* data = (struct online_char_data*)idb_get(online_char_db, sd->account_id); if( data == NULL || data->server == -1) //If it is not in any server, send it offline. [Skotlex] - set_char_offline(99,sd->account_id); + set_char_offline(-1,sd->account_id); if( data != NULL && data->fd == fd) data->fd = -1; } @@ -3224,24 +3237,27 @@ int parse_char(int fd) // request to connect // 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B case 0x65: - if (RFIFOREST(fd) < 17) + if( RFIFOREST(fd) < 17 ) return 0; { + struct auth_node* node; + int GM_value; + int account_id = RFIFOL(fd,2); - int login_id1 = RFIFOL(fd,6); - int login_id2 = RFIFOL(fd,10); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); int sex = RFIFOB(fd,16); + RFIFOSKIP(fd,17); - int GM_value; ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2); if (sd) { //Received again auth packet for already authentified account?? Discard it. //TODO: Perhaps log this as a hack attempt? //TODO: and perhaps send back a reply? - RFIFOSKIP(fd,17); break; } + if( (GM_value = isGM(account_id)) != 0 ) ShowInfo("Account Logged On; Account ID: %d (GM level %d).\n", account_id, GM_value); else @@ -3263,17 +3279,18 @@ int parse_char(int fd) WFIFOSET(fd,4); // search authentification - ARR_FIND( 0, AUTH_FIFO_SIZE, i, - auth_fifo[i].account_id == sd->account_id && - auth_fifo[i].login_id1 == sd->login_id1 && - auth_fifo[i].login_id2 == sd->login_id2 && - auth_fifo[i].ip == session[fd]->client_addr && - auth_fifo[i].delflag == 2 ); - - if( i < AUTH_FIFO_SIZE ) { - auth_fifo[i].delflag = 1; + node = (struct auth_node*)idb_get(auth_db, account_id); + if( node != NULL && + node->account_id == account_id && + node->login_id1 == login_id1 && + node->login_id2 == login_id2 && + node->ip == ipl ) + {// authentication found (coming from map server) + idb_remove(auth_db, account_id); char_auth_ok(fd, sd); - } else { // authentication not found + } + else + {// authentication not found (coming from login server) if (login_fd > 0) { // don't send request if no login-server WFIFOHEAD(login_fd,19); WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account @@ -3281,7 +3298,7 @@ int parse_char(int fd) WFIFOL(login_fd,6) = sd->login_id1; WFIFOL(login_fd,10) = sd->login_id2; WFIFOB(login_fd,14) = sd->sex; - WFIFOL(login_fd,15) = htonl(session[fd]->client_addr); + WFIFOL(login_fd,15) = htonl(ipl); WFIFOSET(login_fd,19); } else { // if no login-server, we must refuse connection WFIFOHEAD(fd,3); @@ -3291,17 +3308,17 @@ int parse_char(int fd) } } } - - RFIFOSKIP(fd,17); break; // char select case 0x66: FIFOSD_CHECK(3); { - int slot = RFIFOB(fd,2); struct mmo_charstatus *cd; + uint32 subnet_map_ip; + struct auth_node* node; + int slot = RFIFOB(fd,2); RFIFOSKIP(fd,3); // if we activated email creation and email is default email @@ -3369,33 +3386,8 @@ int parse_char(int fd) cd->last_point.map = j; } - //Send player to map - WFIFOHEAD(fd,28); - WFIFOW(fd,0) = 0x71; - WFIFOL(fd,2) = cd->char_id; - mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); - { - // Advanced subnet check [LuzZza] - uint32 subnet_map_ip; - subnet_map_ip = lan_subnetcheck(ipl); - WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip); - WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] - WFIFOSET(fd,28); - } - ShowInfo("Character selection '%s' (account: %d, slot: %d).\n", cd->name, sd->account_id, ch); - - if (auth_fifo_pos >= AUTH_FIFO_SIZE) - auth_fifo_pos = 0; - auth_fifo[auth_fifo_pos].account_id = sd->account_id; - auth_fifo[auth_fifo_pos].char_id = cd->char_id; - auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1; - auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2; - auth_fifo[auth_fifo_pos].delflag = 0; - auth_fifo[auth_fifo_pos].sex = sd->sex; - auth_fifo[auth_fifo_pos].expiration_time = sd->expiration_time; - auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; - //Send NEW auth packet [Kevin] + //FIXME: is this case even possible? [ultramage] if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL) { ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); @@ -3409,19 +3401,43 @@ int parse_char(int fd) break; } - //Send auth to server. - WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus)); + //Send player to map + WFIFOHEAD(fd,28); + WFIFOW(fd,0) = 0x71; + WFIFOL(fd,2) = cd->char_id; + mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); + + // Advanced subnet check [LuzZza] + subnet_map_ip = lan_subnetcheck(ipl); + WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip); + WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] + WFIFOSET(fd,28); + + ShowInfo("Character selection '%s' (account: %d, slot: %d).\n", cd->name, sd->account_id, ch); + + //Send auth ok to map server + WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus)); WFIFOW(map_fd,0) = 0x2afd; WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus); - WFIFOL(map_fd,4) = auth_fifo[auth_fifo_pos].account_id; - WFIFOL(map_fd,8) = auth_fifo[auth_fifo_pos].login_id1; - WFIFOL(map_fd,16) = auth_fifo[auth_fifo_pos].login_id2; - WFIFOL(map_fd,12) = (unsigned long)auth_fifo[auth_fifo_pos].expiration_time; + WFIFOL(map_fd,4) = sd->account_id; + WFIFOL(map_fd,8) = sd->login_id1; + WFIFOL(map_fd,16) = sd->login_id2; + WFIFOL(map_fd,12) = (unsigned long)sd->expiration_time; memcpy(WFIFOP(map_fd,20), cd, sizeof(struct mmo_charstatus)); WFIFOSET(map_fd, WFIFOW(map_fd,2)); + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = sd->account_id; + node->char_id = cd->char_id; + node->login_id1 = sd->login_id1; + node->login_id2 = sd->login_id2; + node->sex = sd->sex; + node->expiration_time = sd->expiration_time; + node->ip = ipl; + idb_put(auth_db, sd->account_id, node); + set_char_online(i, cd->char_id, cd->account_id); - auth_fifo_pos++; } break; @@ -4158,6 +4174,7 @@ void do_final(void) online_char_db->clear(online_char_db, NULL); //clean the db... create_online_files(); online_char_db->destroy(online_char_db, NULL); //dispose the db... + auth_db->destroy(auth_db, NULL); if(gm_account) aFree(gm_account); if(char_dat) aFree(char_dat); @@ -4219,6 +4236,7 @@ int do_init(int argc, char **argv) char_log("The char-server starting...\n"); ShowInfo("Initializing char server.\n"); + auth_db = idb_alloc(DB_OPT_RELEASE_DATA); online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); mmo_char_init(); char_read_fame_list(); //Read fame lists. |