diff options
-rw-r--r-- | Changelog-Trunk.txt | 7 | ||||
-rw-r--r-- | src/char/char.c | 177 | ||||
-rw-r--r-- | src/char_sql/char.c | 171 | ||||
-rw-r--r-- | src/map/trade.c | 5 |
4 files changed, 169 insertions, 191 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index b16189003..02a6d619b 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,13 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2007/03/01 + * Added a check to prevent trades from being commited if either character + is in final-save state. + * Checked and cleaned up the online_check code in the char-server. Further + connections to the char-server are rejected when the account already has a + connection (previously this would happen only if there was already another + character IN game, not just waiting on the char-select screen). [Skotlex] 2007/02/28 * Added the source and VC8 project for my experimental mapcache generator; it is NOT compatible with eA's current mapcache but uses a brand new format diff --git a/src/char/char.c b/src/char/char.c index cc6b12d8e..9a251d733 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -157,6 +157,7 @@ static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CH struct online_char_data { int account_id; int char_id; + int fd; short server; unsigned waiting_disconnect :1; }; @@ -289,6 +290,7 @@ static void * create_online_char_data(DBKey key, va_list args) { character->account_id = key.i; character->char_id = -1; character->server = -1; + character->fd = -1; return character; } @@ -1926,6 +1928,52 @@ static int char_delete(struct mmo_charstatus *cs) { return 0; } +static void char_auth_ok(int fd, struct char_session_data *sd) +{ + struct online_char_data* character; + if (max_connect_user && count_users() >= max_connect_user && + isGM(sd->account_id) < gm_allow_level) { + // refuse connection (over populated) + WFIFOW(fd,0) = 0x6c; + WFIFOW(fd,2) = 0; + WFIFOSET(fd,3); + return; + } + + if (online_check && (character = idb_get(online_char_db, sd->account_id))) + { // check if character is not online already. [Skotlex] + if (character->server > -1) + { //Character already online. KICK KICK KICK + mapif_disconnectplayer(server_fd[character->server], + character->account_id, character->char_id, 2); + if (!character->waiting_disconnect) + add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); + character->waiting_disconnect = 1; + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 8; + WFIFOSET(fd,3); + return; + } + if (character->fd >= 0 && character->fd != fd) + { //There's already a connection from this account that hasn't picked a char yet. + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 8; + WFIFOSET(fd,3); + return; + } + character->fd = fd; + } + if (login_fd > 0) { + // request to login-server to obtain e-mail/time limit + WFIFOHEAD(login_fd, 6); + WFIFOW(login_fd,0) = 0x2716; + WFIFOL(login_fd,2) = sd->account_id; + WFIFOSET(login_fd,6); + } + // send characters to player + mmo_char_send006b(fd, sd); +} + int send_accounts_tologin(int tid, unsigned int tick, int id, int data); int parse_tologin(int fd) { @@ -1981,38 +2029,23 @@ int parse_tologin(int fd) { case 0x2713: if (RFIFOREST(fd) < 51) return 0; -// printf("parse_tologin 2713 : %d\n", RFIFOB(fd,6)); - for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == RFIFOL(fd,2)) { - if (RFIFOB(fd,6) != 0) { - WFIFOHEAD(i, 3); - WFIFOW(i,0) = 0x6c; - WFIFOB(i,2) = 0x42; - WFIFOSET(i,3); - } else if (max_connect_user == 0 || count_users() < max_connect_user) { -// if (max_connect_user == 0) -// printf("max_connect_user (unlimited) -> accepted.\n"); -// else -// printf("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user); - memcpy(sd->email, RFIFOP(fd, 7), 40); - if (e_mail_check(sd->email) == 0) - strncpy(sd->email, "a@a.com", 40); // default e-mail - sd->connect_until_time = (time_t)RFIFOL(fd,47); - // send characters to player - mmo_char_send006b(i, sd); - } else if(isGM(sd->account_id) >= gm_allow_level) { - sd->connect_until_time = (time_t)RFIFOL(fd,47); - // send characters to player - mmo_char_send006b(i, sd); - } else { - // refuse connection: too much online players -// printf("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user); - WFIFOHEAD(i, 3); - WFIFOW(i,0) = 0x6c; - WFIFOW(i,2) = 0; - WFIFOSET(i,3); - } - break; + for(i = 0; i < fd_max && !( + session[i] && + (sd = (struct char_session_data*)session[i]->session_data) && + sd->account_id == RFIFOL(fd,2)) + ; i++); + if (i < fd_max) { + if (RFIFOB(fd,6) != 0) { + WFIFOHEAD(i, 3); + WFIFOW(i,0) = 0x6c; + WFIFOB(i,2) = 0x42; + WFIFOSET(i,3); + } else { + memcpy(sd->email, RFIFOP(fd, 7), 40); + if (e_mail_check(sd->email) == 0) + strncpy(sd->email, "a@a.com", 40); // default e-mail + sd->connect_until_time = (time_t)RFIFOL(fd,47); + char_auth_ok(i, sd); } } RFIFOSKIP(fd,51); @@ -3327,6 +3360,8 @@ int parse_char(int fd) { struct online_char_data* data = idb_get(online_char_db, sd->account_id); if (!data || data->server== -1) //If it is not in any server, send it offline. [Skotlex] set_char_offline(99,sd->account_id); + if (data && data->fd == fd) + data->fd = -1; } do_close(fd); return 0; @@ -3385,74 +3420,20 @@ int parse_char(int fd) { WFIFOL(fd,0) = RFIFOL(fd,2); WFIFOSET(fd,4); // search authentification - for(i = 0; i < AUTH_FIFO_SIZE; i++) { - if (auth_fifo[i].account_id == sd->account_id && - auth_fifo[i].login_id1 == sd->login_id1 && + for(i = 0; i < AUTH_FIFO_SIZE && !( + auth_fifo[i].account_id == sd->account_id && + auth_fifo[i].login_id1 == sd->login_id1 && #if CMP_AUTHFIFO_LOGIN2 != 0 - auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18 + auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18 #endif - (!check_ip_flag || auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr) && - auth_fifo[i].delflag == 2) { - auth_fifo[i].delflag = 1; - - if (online_check) - { // check if character is not online already. [Skotlex] - struct online_char_data* character; - character = idb_get(online_char_db, sd->account_id); - - if (character) - { - if(character->server > -1) - { //Kick it from the map server it is on. - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); - if (!character->waiting_disconnect) - add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); - character->waiting_disconnect = 1; - /* Not a good idea because this would trigger when you do a char-change from the map server! [Skotlex] - } else { //Manual kick from char server. - struct char_session_data *tsd; - int i; - for(i = 0; i < fd_max; i++) { - if (session[i] && i!=fd && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == sd->account_id) - { - WFIFOW(i,0) = 0x81; - WFIFOB(i,2) = 2; - WFIFOSET(i,3); - break; - } - } - if (i == fd_max) //Shouldn't happen, but just in case. - set_char_offline(99, sd->account_id); - */ - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 8; - WFIFOSET(fd,3); - break; - } - } - } - - if (max_connect_user == 0 || count_users() < max_connect_user) { - if (login_fd > 0) { // don't send request if no login-server - // request to login-server to obtain e-mail/time limit - WFIFOHEAD(login_fd, 6); - WFIFOW(login_fd,0) = 0x2716; - WFIFOL(login_fd,2) = sd->account_id; - WFIFOSET(login_fd,6); - } - // send characters to player - mmo_char_send006b(fd, sd); - } else { - // refuse connection (over populated) - WFIFOW(fd,0) = 0x6c; - WFIFOW(fd,2) = 0; - WFIFOSET(fd,3); - } - break; - } - } - // authentification not found - if (i == AUTH_FIFO_SIZE) { + (!check_ip_flag || auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr) && + auth_fifo[i].delflag == 2) + ; i++); + + if (i < AUTH_FIFO_SIZE) { + auth_fifo[i].delflag = 1; + char_auth_ok(fd, sd); + } else { // authentification not found 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 diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 481b9a34e..c6a8e606e 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -180,6 +180,7 @@ int console = 0; struct online_char_data { int account_id; int char_id; + int fd; short server; unsigned waiting_disconnect :1; }; @@ -204,6 +205,7 @@ static void * create_online_char_data(DBKey key, va_list args) { character->account_id = key.i; character->char_id = -1; character->server = -1; + character->fd = -1; return character; } @@ -1787,6 +1789,53 @@ int mmo_char_send006b(int fd, struct char_session_data *sd) { return 0; } +static void char_auth_ok(int fd, struct char_session_data *sd) +{ + struct online_char_data* character; + if (max_connect_user && count_users() >= max_connect_user && + isGM(sd->account_id) < gm_allow_level) { + // refuse connection (over populated) + WFIFOW(fd,0) = 0x6c; + WFIFOW(fd,2) = 0; + WFIFOSET(fd,3); + return; + } + + if (online_check && (character = idb_get(online_char_db, sd->account_id))) + { // check if character is not online already. [Skotlex] + if (character->server > -1) + { //Character already online. KICK KICK KICK + mapif_disconnectplayer(server_fd[character->server], + character->account_id, character->char_id, 2); + if (!character->waiting_disconnect) + add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); + character->waiting_disconnect = 1; + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 8; + WFIFOSET(fd,3); + return; + } + if (character->fd >= 0 && character->fd != fd) + { //There's already a connection from this account that hasn't picked a char yet. + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 8; + WFIFOSET(fd,3); + return; + } + character->fd = fd; + } + if (login_fd > 0) { + // request to login-server to obtain e-mail/time limit + WFIFOHEAD(login_fd, 6); + WFIFOW(login_fd,0) = 0x2716; + WFIFOL(login_fd,2) = sd->account_id; + WFIFOSET(login_fd,6); + } + // send characters to player + mmo_char_send006b(fd, sd); +} + + int send_accounts_tologin(int tid, unsigned int tick, int id, int data); int parse_tologin(int fd) { @@ -1845,34 +1894,23 @@ int parse_tologin(int fd) { case 0x2713: if(RFIFOREST(fd)<51) return 0; - for(i = 0; i < fd_max; i++) { - if (session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == RFIFOL(fd,2)) { + + for(i = 0; i < fd_max && !( + session[i] && + (sd = (struct char_session_data*)session[i]->session_data) && + sd->account_id == RFIFOL(fd,2)) + ; i++); + + if (i < fd_max) { + if (RFIFOB(fd,6) != 0) { WFIFOHEAD(i,3); - if (RFIFOB(fd,6) != 0) { - WFIFOW(i,0) = 0x6c; - WFIFOB(i,2) = 0x42; - WFIFOSET(i,3); - } else if (max_connect_user == 0 || count_users() < max_connect_user) { -// if (max_connect_user == 0) -// printf("max_connect_user (unlimited) -> accepted.\n"); -// else -// printf("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user); - sd->connect_until_time = (time_t)RFIFOL(fd,47); - memcpy(sd->email, RFIFOP(fd, 7), 40); - // send characters to player - mmo_char_send006b(i, sd); - } else if(isGM(sd->account_id) >= gm_allow_level) { - sd->connect_until_time = (time_t)RFIFOL(fd,47); - memcpy(sd->email, RFIFOP(fd, 7), 40); - // send characters to player - mmo_char_send006b(i, sd); - } else { - // refuse connection: too much online players -// printf("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user); - WFIFOW(i,0) = 0x6c; - WFIFOW(i,2) = 0; - WFIFOSET(i,3); - } + WFIFOW(i,0) = 0x6c; + WFIFOB(i,2) = 0x42; + WFIFOSET(i,3); + } else { + sd->connect_until_time = (time_t)RFIFOL(fd,47); + memcpy(sd->email, RFIFOP(fd, 7), 40); + char_auth_ok(i, sd); } } RFIFOSKIP(fd,51); @@ -3136,6 +3174,8 @@ int parse_char(int fd) { struct online_char_data* data = idb_get(online_char_db, sd->account_id); if (!data || data->server== -1) //If it is not in any server, send it offline. [Skotlex] set_char_offline(99,sd->account_id); + if (data && data->fd == fd) + data->fd = -1; } do_close(fd); return 0; @@ -3190,74 +3230,21 @@ int parse_char(int fd) { WFIFOL(fd, 0) = RFIFOL(fd, 2); WFIFOSET(fd, 4); - for(i = 0; i < AUTH_FIFO_SIZE; i++) { - if (auth_fifo[i].account_id == sd->account_id && - auth_fifo[i].login_id1 == sd->login_id1 && + for(i = 0; + i < AUTH_FIFO_SIZE && !( + auth_fifo[i].account_id == sd->account_id && + auth_fifo[i].login_id1 == sd->login_id1 && #if CMP_AUTHFIFO_LOGIN2 != 0 - auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18 + auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18 #endif - (!check_ip_flag || auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr) && - auth_fifo[i].delflag == 2) { + (!check_ip_flag || auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr) && + auth_fifo[i].delflag == 2) + ; i++); + + if (i < AUTH_FIFO_SIZE) { auth_fifo[i].delflag = 1; - - if (online_check) - { // check if character is not online already. [Skotlex] - struct online_char_data* character; - character = idb_get(online_char_db, sd->account_id); - - if (character) - { - if (character->server > -1) - { //Character already online. KICK KICK KICK - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); - if (!character->waiting_disconnect) - add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); - character->waiting_disconnect = 1; - /* Not a good idea because this would trigger when you do a char-change from the map server! [Skotlex] - } else { //Kick from char server. - struct char_session_data *tsd; - int i; - for(i = 0; i < fd_max; i++) { - if (session[i] && i != fd && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == sd->account_id) - { - WFIFOW(i,0) = 0x81; - WFIFOB(i,2) = 2; - WFIFOSET(i,3); - break; - } - if (i == fd_max) //Shouldn't happen, but just in case. - set_char_offline(99, sd->account_id); - } - */ - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 8; - WFIFOSET(fd,3); - break; - } - } - } - - if (max_connect_user == 0 || count_users() < max_connect_user) { - if (login_fd > 0) { // don't send request if no login-server - // request to login-server to obtain e-mail/time limit - WFIFOHEAD(login_fd, 6); - WFIFOW(login_fd,0) = 0x2716; - WFIFOL(login_fd,2) = sd->account_id; - WFIFOSET(login_fd,6); - } - // send characters to player - mmo_char_send006b(fd, sd); - } else { - // refuse connection (over populated) - WFIFOW(fd,0) = 0x6c; - WFIFOW(fd,2) = 0; - WFIFOSET(fd,3); - } -// printf("connection request> set delflag 1(o:2)- account_id:%d/login_id1:%d(fifo_id:%d)\n", sd->account_id, sd->login_id1, i); - break; - } - } - if (i == AUTH_FIFO_SIZE) { + char_auth_ok(fd, sd); + } else { 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 diff --git a/src/map/trade.c b/src/map/trade.c index f6c587ddb..e4bb4a4b1 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -162,7 +162,7 @@ int impossible_trade_check(struct map_session_data *sd) { nullpo_retr(1, sd); - if(sd->deal.zeny > sd->status.zeny) + if(sd->deal.zeny > sd->status.zeny) { pc_setglobalreg(sd,"ZENY_HACKER",1); return -1; @@ -223,6 +223,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) { struct item_data *data; int trade_i, i, amount, n; + if(sd->state.finalsave || tsd->state.finalsave) + return 0; //Item transferring fails + // check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then. if(sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny)) return 0; |