From 8c8ef2dd18e2e729450a59e18c6d6b0df9dc4a09 Mon Sep 17 00:00:00 2001 From: glighta Date: Wed, 5 Dec 2012 14:16:04 +0000 Subject: - Re-committed r16985 (pid:161281). git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@17001 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/char/char.c | 156 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 73 deletions(-) (limited to 'src/char') diff --git a/src/char/char.c b/src/char/char.c index 0003e590f..eb214fedf 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -243,7 +243,7 @@ void set_char_online(int map_id, int char_id, int account_id) { struct online_char_data* character; struct mmo_charstatus *cp; - + //Update DB if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) Sql_ShowDebug(sql_handle); @@ -787,7 +787,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); - + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { Sql_ShowDebug(sql_handle); @@ -858,19 +858,19 @@ int inventory_to_sql(const struct item items[], int max, int id) { bool* flag; // bit array for inventory matching bool found; int errors = 0; - - + + // The following code compares inventory with current database values // and performs modification/deletion/insertion only on relevant rows. // This approach is more complicated than a trivial delete&insert, but // it significantly reduces cpu load on the database server. - + StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id); - + stmt = SqlStmt_Malloc(sql_handle); if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_ERROR == SqlStmt_Execute(stmt) ) @@ -880,7 +880,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { StringBuf_Destroy(&buf); return 1; } - + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); @@ -892,10 +892,10 @@ int inventory_to_sql(const struct item items[], int max, int id) { SqlStmt_BindColumn(stmt, 8, SQLDT_CHAR, &item.favorite, 0, NULL, NULL); for( j = 0; j < MAX_SLOTS; ++j ) SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); - + // bit array indicating which inventory items have already been matched flag = (bool*) aCalloc(max, sizeof(bool)); - + while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) { found = false; // search for the presence of the item in the char's inventory @@ -903,7 +903,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { // skip empty and already matched entries if( items[i].nameid == 0 || flag[i] ) continue; - + if( items[i].nameid == item.nameid && items[i].card[0] == item.card[0] && items[i].card[2] == item.card[2] @@ -927,13 +927,13 @@ int inventory_to_sql(const struct item items[], int max, int id) { for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); - + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; } } - + found = flag[i] = true; //Item dealt with, break; //skip to next item in the db. } @@ -946,40 +946,40 @@ int inventory_to_sql(const struct item items[], int max, int id) { } } SqlStmt_Free(stmt); - + StringBuf_Clear(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`", inventory_db); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_AppendStr(&buf, ") VALUES "); - + found = false; // insert non-matched items into the db as new items for( i = 0; i < max; ++i ) { // skip empty and already matched entries if( items[i].nameid == 0 || flag[i] ) continue; - + if( found ) StringBuf_AppendStr(&buf, ","); else found = true; - + StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%d'", id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", '%d'", items[i].card[j]); StringBuf_AppendStr(&buf, ")"); } - + if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; } - + StringBuf_Destroy(&buf); aFree(flag); - + return errors; } @@ -1090,7 +1090,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything #endif memset(p, 0, sizeof(struct mmo_charstatus)); - + if (save_log) ShowInfo("Char load request (%d)\n", char_id); stmt = SqlStmt_Malloc(sql_handle); @@ -1139,7 +1139,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything || SQL_ERROR == SqlStmt_BindColumn(stmt, 26, SQLDT_INT, &p->guild_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 27, SQLDT_INT, &p->pet_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 28, SQLDT_INT, &p->hom_id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_INT, &p->ele_id, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_INT, &p->ele_id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL) @@ -1362,7 +1362,7 @@ int rename_char_sql(struct char_session_data *sd, int char_id) if( sd->new_name[0] == 0 ) // Not ready for rename return 2; - + if( !mmo_char_fromsql(char_id, &char_dat, false) ) // Only the short data is needed. return 2; @@ -1478,7 +1478,7 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag //check other inputs #if PACKETVER >= 20120307 - if(slot >= MAX_CHARS) + if(slot >= MAX_CHARS) #else if((slot >= MAX_CHARS) // slots || (str + agi + vit + int_ + dex + luk != 6*5 ) // stats @@ -1532,7 +1532,7 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag { Sql_ShowDebug(sql_handle); return -2; //No, stop the procedure! - } + } #endif //Retrieve the newly auto-generated char id char_id = (int)Sql_LastInsertId(sql_handle); @@ -1580,11 +1580,11 @@ int delete_char_sql(int char_id) { char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1]; //Name needs be escaped. - int account_id, party_id, guild_id, hom_id, base_level, partner_id, father_id, mother_id; - char* data; + int account_id, party_id, guild_id, hom_id, base_level, partner_id, father_id, mother_id, elemental_id; + char *data; size_t len; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id)) Sql_ShowDebug(sql_handle); if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) @@ -1603,6 +1603,8 @@ int delete_char_sql(int char_id) Sql_GetData(sql_handle, 6, &data, NULL); partner_id = atoi(data); Sql_GetData(sql_handle, 7, &data, NULL); father_id = atoi(data); Sql_GetData(sql_handle, 8, &data, NULL); mother_id = atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); + elemental_id = atoi(data); Sql_EscapeStringLen(sql_handle, esc_name, name, min(len, NAME_LENGTH)); Sql_FreeResult(sql_handle); @@ -1652,11 +1654,15 @@ int delete_char_sql(int char_id) if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, cart_db, cart_db, char_id) ) Sql_ShowDebug(sql_handle); - /* remove homunculus */ + /* remove homunculus */ if( hom_id ) mapif_homunculus_delete(hom_id); - /* remove mercenary data */ + /* remove elemental */ + if (elemental_id) + mapif_elemental_delete(elemental_id); + + /* remove mercenary data */ mercenary_owner_delete(char_id); /* delete char's friends list */ @@ -1689,11 +1695,15 @@ int delete_char_sql(int char_id) /* delete character registry */ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) Sql_ShowDebug(sql_handle); - + /* delete skills */ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) ) Sql_ShowDebug(sql_handle); - + + /* delete mails (only received) */ + if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", mail_db, char_id)) + Sql_ShowDebug(sql_handle); + #ifdef ENABLE_SC_SAVING /* status changes */ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) ) @@ -1774,10 +1784,10 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed; WBUFW(buf,52) = p->class_; WBUFW(buf,54) = p->hair; - + //When the weapon is sent and your option is riding, the client crashes on login!? WBUFW(buf,56) = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon; - + WBUFW(buf,58) = p->base_level; WBUFW(buf,60) = min(p->skill_point, INT16_MAX); WBUFW(buf,62) = p->head_bottom; @@ -2015,7 +2025,7 @@ void loginif_on_ready(void) int i; loginif_check_shutdown(); - + //Send online accounts to login server. send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); @@ -2029,7 +2039,7 @@ void loginif_on_ready(void) int parse_fromlogin(int fd) { struct char_session_data* sd = NULL; int i; - + // only process data from the login-server if( fd != login_fd ) { ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); @@ -2228,9 +2238,9 @@ int parse_fromlogin(int fd) { class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); } - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) - Sql_ShowDebug(sql_handle); - + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) + Sql_ShowDebug(sql_handle); + if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); } @@ -2366,7 +2376,7 @@ void do_init_loginif(void) // establish char-login connection if not present add_timer_func_list(check_connect_login_server, "check_connect_login_server"); add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); - + // send a list of all online account IDs to login server add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour @@ -2471,7 +2481,7 @@ int char_send_fame_list(int fd) { int i, len = 8; unsigned char buf[32000]; - + WBUFW(buf,0) = 0x2b1b; for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) { @@ -2630,7 +2640,7 @@ int parse_frommap(int fd) ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", id, j, CONVIP(server[id].ip), server[id].port); ShowStatus("Map-server %d loading complete.\n", id); - + // send name for wisp to player WFIFOHEAD(fd, 3 + NAME_LENGTH); WFIFOW(fd,0) = 0x2afb; @@ -2816,7 +2826,7 @@ int parse_frommap(int fd) uint32 login_id2 = RFIFOL(fd,10); uint32 ip = RFIFOL(fd,14); RFIFOSKIP(fd,18); - + if( runflag != CHARSERVER_ST_RUNNING ) { WFIFOHEAD(fd,7); @@ -2869,7 +2879,7 @@ int parse_frommap(int fd) mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } - + if( runflag == CHARSERVER_ST_RUNNING && session_isActive(map_fd) && char_data ) @@ -3147,7 +3157,7 @@ int parse_frommap(int fd) set_all_offline(id); RFIFOSKIP(fd,2); break; - + case 0x2b19: // Character set online [Wizputer] if (RFIFOREST(fd) < 10) return 0; @@ -3236,7 +3246,7 @@ int parse_frommap(int fd) } if( runflag == CHARSERVER_ST_RUNNING && cd != NULL && - node != NULL && + node != NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 && @@ -3288,29 +3298,29 @@ int parse_frommap(int fd) else { int sfd;/* stat server fd */ RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ - + if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true) ) == -1 ) { RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ break;/* connection not possible, we drop the report */ } - + session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */ - + WFIFOHEAD(sfd, RFIFOW(fd,2) ); - + memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2)); - + WFIFOSET(sfd, RFIFOW(fd,2) ); - + flush_fifo(sfd); - + do_close(sfd); - + RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ } break; - + default: { // inter server - packet @@ -3325,7 +3335,7 @@ int parse_frommap(int fd) } } // switch } // while - + return 0; } @@ -3348,7 +3358,7 @@ void do_final_mapif(void) int search_mapserver(unsigned short map, uint32 ip, uint16 port) { int i, j; - + for(i = 0; i < ARRAYLENGTH(server); i++) { if (server[i].fd > 0 @@ -3458,9 +3468,9 @@ static void char_delete2_req(int fd, struct char_session_data* sd) char_delete2_ack(fd, char_id, 3, 0); return; } - + Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); - + if( delete_date ) {// character already queued for deletion char_delete2_ack(fd, char_id, 0, 0); return; @@ -3660,7 +3670,7 @@ int parse_char(int fd) //TODO: and perhaps send back a reply? break; } - + CREATE(session[fd]->session_data, struct char_session_data, 1); sd = (struct char_session_data*)session[fd]->session_data; sd->account_id = account_id; @@ -3918,9 +3928,9 @@ int parse_char(int fd) ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); memcpy(email, RFIFOP(fd,6), 40); RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); - - // Check if e-mail is correct - if(strcmpi(email, sd->email) && //email does not matches and + + // Check if e-mail is correct + if(strcmpi(email, sd->email) && //email does not matches and ( strcmp("a@a.com", sd->email) || //it is not default email, or (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default @@ -3947,7 +3957,7 @@ int parse_char(int fd) for(ch = i; ch < MAX_CHARS-1; ch++) sd->found_char[ch] = sd->found_char[ch+1]; sd->found_char[MAX_CHARS-1] = -1; - + /* Delete character */ if(delete_char_sql(cid)<0){ //can't delete the char @@ -3998,7 +4008,7 @@ int parse_char(int fd) i = 1; safestrncpy(sd->new_name, name, NAME_LENGTH); } - else + else i = 0; WFIFOHEAD(fd, 4); @@ -4279,7 +4289,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data session[login_fd]->func_parse = parse_fromlogin; session[login_fd]->flag.server = 1; realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - + WFIFOHEAD(login_fd,86); WFIFOW(login_fd,0) = 0x2710; memcpy(WFIFOP(login_fd,2), userid, 24); @@ -4292,7 +4302,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data WFIFOW(login_fd,82) = char_maintenance; WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin] WFIFOSET(login_fd,86); - + return 1; } @@ -4342,7 +4352,7 @@ int char_lan_config_read(const char *lancfgName) FILE *fp; int line_num = 0; char line[1024], w1[64], w2[64], w3[64], w4[64]; - + if((fp = fopen(lancfgName, "r")) == NULL) { ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName); return 1; @@ -4354,7 +4364,7 @@ int char_lan_config_read(const char *lancfgName) continue; if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4) { - + ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num); continue; } @@ -4375,7 +4385,7 @@ int char_lan_config_read(const char *lancfgName) ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4); continue; } - + subnet_count++; } } @@ -4639,7 +4649,7 @@ void do_final(void) inter_final(); flush_fifos(); - + do_final_mapif(); do_final_loginif(); @@ -4711,7 +4721,7 @@ int do_init(int argc, char **argv) } inter_init_sql((argc > 2) ? argv[2] : inter_cfgName); // inter server configuration - + auth_db = idb_alloc(DB_OPT_RELEASE_DATA); online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); mmo_char_sql_init(); @@ -4754,7 +4764,7 @@ int do_init(int argc, char **argv) { //##TODO invoke a CONSOLE_START plugin event } - + //Cleaning the tables for NULL entrys @ startup [Sirius] //Chardb clean if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '0'", char_db) ) @@ -4771,7 +4781,7 @@ int do_init(int argc, char **argv) set_defaultparse(parse_char); char_fd = make_listen_bind(bind_ip, char_port); ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); - + if( runflag != CORE_ST_STOP ) { shutdown_callback = do_shutdown; -- cgit v1.2.3-70-g09d2