From 281c9af55b9751de6a4e0c715064513f2deca6c5 Mon Sep 17 00:00:00 2001 From: ultramage Date: Sat, 22 Sep 2007 12:29:45 +0000 Subject: Fixed a severe bug in inventory saving code (caused by r11192). The fix was to revert the changes; I totally misunderstood how it was supposed to work... git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11275 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 9 +++-- src/char_sql/char.c | 104 +++++++++++++++++++++++----------------------------- 2 files changed, 51 insertions(+), 62 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 61e5d399f..f43f917a3 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,10 +4,7 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2007/09/22 - * Updated sql files [Playtester] - * Added a sanity check for MAX_ZENY (doesn't compile if too big). - * Redid the buildin_query_sql function. (fixes bugreport:81). [FlavioJS] -2007/09/21 + * Fixed a severe bug in inventory saving code (caused by r11192) * Applied changes to clif_parse_globalmessage() from my WiP code - clearer processing of the individual packet components - proper code ordering, some more integrity checks @@ -15,6 +12,10 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. - global chat logging no longer logs the entire string (w/ player name) * Fixed global chat logging always crashing on a null pointer * Added 'safestrnlen' to prevent null pointer crashes [ultramage] + * Updated sql files [Playtester] + * Added a sanity check for MAX_ZENY (doesn't compile if too big). + * Redid the buildin_query_sql function. (fixes bugreport:81). [FlavioJS] +2007/09/21 * itemdb.c/h using a static array of 32k struct item_data* entries (faster itemdb loockup and a first step to remove map_session_data->inventory_data). * Fixed a typo in the configure script that replaced CFLAGS with CPPFLAGS diff --git a/src/char_sql/char.c b/src/char_sql/char.c index b493028b8..5579719c4 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -410,26 +410,7 @@ void read_gm_account(void) mapif_send_gmaccounts(); } -#endif //TXT_SQL_CONVERT -int compare_item(const struct item* a, const struct item* b) -{ - - if(a->id == b->id && - a->nameid == b->nameid && - a->amount == b->amount && - a->equip == b->equip && - a->identify == b->identify && - a->refine == b->refine && - a->attribute == b->attribute) - { - int i; - for (i=0; icard[i]==b->card[i]; i++); - return (i == MAX_SLOTS); - } - return 0; -} -#ifndef TXT_SQL_CONVERT static void* create_charstatus(DBKey key, va_list args) { struct mmo_charstatus *cp; @@ -750,38 +731,44 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) { - bool found = false; + found = false; // search for the presence of the item in the char's inventory for( i = 0; i < max; ++i ) { - if( flag[i] ) - continue; // this item was matched already, skip it - - if( items[i].id == 0 ) - { // to make skipping empty entries faster and to prevent saving them later - flag[i] = true; + // skip empty and already matched entries + if( items[i].nameid == 0 || flag[i] ) continue; - } - - if( compare_item(&items[i], &item) ) - ; // Equal - do nothing. - else - { - // update all fields. - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d'", - tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); - StringBuf_Printf(&buf, ", `amount`='%d' WHERE `id`='%d' LIMIT 1", items[i].amount, item.id); - - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) - Sql_ShowDebug(sql_handle); + if( items[i].nameid == item.nameid + && items[i].card[0] == item.card[0] + && items[i].card[2] == item.card[2] + && items[i].card[3] == item.card[3] + ) { //They are the same item. + ARR_FIND( 0, MAX_SLOTS, j, items[i].card[j] != item.card[j] ); + if( j == MAX_SLOTS && + items[i].amount == item.amount && + items[i].equip == item.equip && + items[i].identify == item.identify && + items[i].refine == item.refine && + items[i].attribute == item.attribute ) + ; //Do nothing. + else + { + // update all fields. + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d'", + tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); + StringBuf_Printf(&buf, ", `amount`='%d' WHERE `id`='%d' LIMIT 1", items[i].amount, item.id); + + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + } + + found = flag[i] = true; //Item dealt with, + break; //skip to next item in the db. } - - found = flag[i] = true; //Item dealt with, - break; //skip to next item in the db. } if( !found ) {// Item not present in inventory, remove it. @@ -799,21 +786,22 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit found = false; // insert non-matched items into the db as new items - for( i = 0, found = 0; i < max; ++i ) + for( i = 0; i < max; ++i ) { - if( !flag[i] ) - { - if( found ) - StringBuf_AppendStr(&buf, ","); - else - found = true; + // skip empty and already matched entries + if( items[i].nameid == 0 || flag[i] ) + continue; - StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d'", - id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); - for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", '%d'", items[i].card[j]); - StringBuf_AppendStr(&buf, ")"); - } + if( found ) + StringBuf_AppendStr(&buf, ","); + else + found = true; + + StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d'", + id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); + 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)) ) -- cgit v1.2.3-70-g09d2