From c0ed836e87a52d107e7ae09d255f662e1417dd89 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Fri, 22 Aug 2014 17:52:15 -0400 Subject: [PATCH] * Changed how the Unique ID System saves and creates IDs for items. (Hercules dd49dbc) - System is now enabled by default. - All non-stackable items that previously existed will get unique IDs if items::item_check is enabled. - Added 'getequipuniqueid' script command to get the unique ID of an equipment on a player. - Don't forget to apply the SQL update! * Renamed SQL update file that applied to logs. --- doc/script_commands.txt | 10 +++- sql-files/main.sql | 3 +- ..._20140713.sql => upgrade_20140713_log.sql} | 0 sql-files/upgrades/upgrade_20140822.sql | 1 + src/char/char.c | 16 ++---- src/char/int_auction.c | 4 -- src/char/int_mail.c | 4 -- src/char/int_storage.h | 1 - src/char/inter.c | 19 ------- src/char/inter.h | 14 ----- src/common/mmo.h | 2 + src/config/core.h | 4 -- src/map/itemdb.c | 52 +++---------------- src/map/itemdb.h | 2 +- src/map/pc.c | 25 ++++++--- src/map/script.c | 41 +++++++++++++++ 16 files changed, 85 insertions(+), 113 deletions(-) rename sql-files/upgrades/{upgrade_20140713.sql => upgrade_20140713_log.sql} (100%) create mode 100644 sql-files/upgrades/upgrade_20140822.sql diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 204b7231b0..87dd2a0365 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -2540,7 +2540,15 @@ armor, but also don't want them to equip if after the check, you would do this: --------------------------------------- -*getequipname() +*getequipuniqueid() + +This function returns the unique ID (as a string) of the item equipped in the equipment slot +specified on the invoking character. If nothing is equipped there, it returns an empty string. +See 'getequipid' for a full list of valid equipment slots. + +--------------------------------------- + +*getequipname() Returns the jname of the item equipped in the specified equipment slot on the invoking character, or an empty string if nothing is equipped in that position. diff --git a/sql-files/main.sql b/sql-files/main.sql index 215ccba7f9..ad5197f33d 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -124,6 +124,7 @@ CREATE TABLE IF NOT EXISTS `char` ( `moves` int(11) unsigned NOT NULL DEFAULT '0', `unban_time` int(11) unsigned NOT NULL default '0', `font` tinyint(3) unsigned NOT NULL default '0', + `uniqueitem_counter` bigint(20) NOT NULL, PRIMARY KEY (`char_id`), UNIQUE KEY `name_key` (`name`), KEY `account_id` (`account_id`), @@ -698,8 +699,6 @@ CREATE TABLE IF NOT EXISTS `interreg` ( `value` varchar(20) NOT NULL, PRIMARY KEY (`varname`) ) ENGINE=InnoDB; -INSERT INTO `interreg` (`varname`, `value`) VALUES -('unique_id', '0'); -- -- Table structure for table `bonus_script` diff --git a/sql-files/upgrades/upgrade_20140713.sql b/sql-files/upgrades/upgrade_20140713_log.sql similarity index 100% rename from sql-files/upgrades/upgrade_20140713.sql rename to sql-files/upgrades/upgrade_20140713_log.sql diff --git a/sql-files/upgrades/upgrade_20140822.sql b/sql-files/upgrades/upgrade_20140822.sql new file mode 100644 index 0000000000..bd8c13d5ff --- /dev/null +++ b/sql-files/upgrades/upgrade_20140822.sql @@ -0,0 +1 @@ +ALTER TABLE `char` ADD COLUMN `uniqueitem_counter` bigint(20) NOT NULL AFTER `font`; diff --git a/src/char/char.c b/src/char/char.c index 8a4486a3cd..96476e8dbb 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1,7 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder - #include #include #include @@ -335,7 +334,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p){ (p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) || (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) || (p->rename != cp->rename) || (p->robe != cp->robe) || (p->character_moves != cp->character_moves) || - (p->unban_time != cp->unban_time) || (p->font != cp->font) + (p->unban_time != cp->unban_time) || (p->font != cp->font) || (p->uniqueitem_counter != cp->uniqueitem_counter) ) { //Save status if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," @@ -345,7 +344,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p){ "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d'," "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," - "`delete_date`='%lu',`robe`='%d',`moves`='%d',`font`='%u'" + "`delete_date`='%lu',`robe`='%d',`moves`='%d',`font`='%u',`uniqueitem_counter`='%u'" " WHERE `account_id`='%d' AND `char_id` = '%d'", schema_config.char_db, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, @@ -356,7 +355,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p){ mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename, (unsigned long)p->delete_date, // FIXME: platform-dependent size - p->robe,p->character_moves,p->font, + p->robe,p->character_moves,p->font, p->uniqueitem_counter, p->account_id, p->char_id) ) { Sql_ShowDebug(sql_handle); @@ -699,10 +698,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", '%hu'", items[i].card[j]); StringBuf_AppendStr(&buf, ")"); - - updateLastUid(items[i].unique_id); // Unique Non Stackable Item ID } - dbUpdateUid(sql_handle); // Unique Non Stackable Item ID if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { @@ -840,10 +836,7 @@ int char_inventory_to_sql(const struct item items[], int max, int id) { for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", '%hu'", items[i].card[j]); StringBuf_AppendStr(&buf, ")"); - - updateLastUid(items[i].unique_id);// Unique Non Stackable Item ID } - dbUpdateUid(sql_handle); if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { Sql_ShowDebug(sql_handle); @@ -989,7 +982,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`," - "`unban_time`,`font`" + "`unban_time`,`font`,`uniqueitem_counter`" " FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) @@ -1048,6 +1041,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every || SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 53, SQLDT_LONG, &p->unban_time, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); diff --git a/src/char/int_auction.c b/src/char/int_auction.c index 64c5d80068..6c1801d14f 100644 --- a/src/char/int_auction.c +++ b/src/char/int_auction.c @@ -91,10 +91,6 @@ unsigned int auction_create(struct auction_data *auction) StringBuf_Printf(&buf, ",'%hu'", auction->item.card[j]); StringBuf_AppendStr(&buf, ")"); - //Unique Non Stackable Item ID - updateLastUid(auction->item.unique_id); - dbUpdateUid(sql_handle); - stmt = SqlStmt_Malloc(sql_handle); if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, auction->seller_name, strnlen(auction->seller_name, NAME_LENGTH)) diff --git a/src/char/int_mail.c b/src/char/int_mail.c index 9ddf4dedd9..c99d647cbd 100644 --- a/src/char/int_mail.c +++ b/src/char/int_mail.c @@ -119,10 +119,6 @@ int mail_savemessage(struct mail_message* msg) StringBuf_Printf(&buf, ", '%hu'", msg->item.card[j]); StringBuf_AppendStr(&buf, ")"); - //Unique Non Stackable Item ID - updateLastUid(msg->item.unique_id); - dbUpdateUid(sql_handle); - // prepare and execute query stmt = SqlStmt_Malloc(sql_handle); if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) diff --git a/src/char/int_storage.h b/src/char/int_storage.h index 811608f82c..adc4bc2e20 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -14,7 +14,6 @@ int inter_guild_storage_delete(int guild_id); int inter_storage_parse_frommap(int fd); -//Exported for use in the TXT-SQL converter. int storage_fromsql(int account_id, struct storage_data* p); int storage_tosql(int account_id,struct storage_data *p); int guild_storage_tosql(int guild_id, struct guild_storage *p); diff --git a/src/char/inter.c b/src/char/inter.c index dbacc260b1..c169df51bb 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -1168,23 +1168,4 @@ int inter_parse_frommap(int fd) return 1; } -uint64 inter_chk_lastuid(int8 flag, uint64 value){ - static uint64 last_updt_uid = 0; - static int8 update = 0; - if(flag) - { - if(last_updt_uid < value){ - last_updt_uid = value; - update = 1; - } - - return 0; - }else if(update) - { - update = 0; - return last_updt_uid; - } - return 0; -} - diff --git a/src/char/inter.h b/src/char/inter.h index 628e9f1f34..d9302ad9f9 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -25,18 +25,4 @@ extern Sql* lsql_handle; int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type); -uint64 inter_chk_lastuid(int8 flag, uint64 value); -#ifdef NSI_UNIQUE_ID - #define updateLastUid(val_) inter_chk_lastuid(1, val_) - #define dbUpdateUid(handler_)\ - { \ - uint64 unique_id_ = inter_chk_lastuid(0, 0); \ - if (unique_id_ && SQL_ERROR == Sql_Query(handler_, "UPDATE `interreg` SET `value`='%"PRIu64"' WHERE `varname`='unique_id'", unique_id_)) \ - Sql_ShowDebug(handler_);\ - } -#else - #define dbUpdateUid(handler_) - #define updateLastUid(val_) -#endif - #endif /* _INTER_SQL_H_ */ diff --git a/src/common/mmo.h b/src/common/mmo.h index 646ee617cf..e1cf9d111a 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -420,6 +420,8 @@ struct mmo_charstatus { unsigned char font; bool cashshop_sent; // Whether the player has received the CashShop list + + uint32 uniqueitem_counter; }; typedef enum mail_status { diff --git a/src/config/core.h b/src/config/core.h index 83903ccf44..e8c0fa0dfd 100644 --- a/src/config/core.h +++ b/src/config/core.h @@ -48,10 +48,6 @@ /// - but is not the official behaviour. //#define CIRCULAR_AREA -/// Uncomment to enable Non Stackable items unique ID -/// By enabling it, the system will create an unique id for each new non stackable item created -//#define NSI_UNIQUE_ID - /// Comment to disable Guild/Party Bound item system /// By default, we recover/remove Guild/Party Bound items automatically #define BOUND_ITEMS diff --git a/src/map/itemdb.c b/src/map/itemdb.c index d47dc75fd3..687aed8873 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1430,52 +1430,13 @@ static int itemdb_read_sqldb(void) { return 0; } -/** Unique item ID function -* Only one operation by once -* @param flag -* 0 return new id -* 1 set new value, checked with current value -* 2 set new value bypassing anything -* 3/other -* @param value -* @return last value -*------------------------------------------*/ -uint64 itemdb_unique_id(int8 flag, int64 value) { - static uint64 item_uid = 0; - - if(flag) - { - if(flag == 1) - { if(item_uid < value) - return (item_uid = value); - }else if(flag == 2) - return (item_uid = value); - - return item_uid; - } - - return ++item_uid; -} - /** -* Load Unique ID for Item -*/ -static void itemdb_uid_load(void){ - - char * uid; - if (SQL_ERROR == Sql_Query(mmysql_handle, "SELECT `value` FROM `interreg` WHERE `varname`='unique_id'")) - Sql_ShowDebug(mmysql_handle); - - if( SQL_SUCCESS != Sql_NextRow(mmysql_handle) ) - { - ShowError("itemdb_uid_load: Unable to fetch unique_id data\n"); - Sql_FreeResult(mmysql_handle); - return; - } - - Sql_GetData(mmysql_handle, 0, &uid, NULL); - itemdb_unique_id(1, (uint64)strtoull(uid, NULL, 10)); - Sql_FreeResult(mmysql_handle); + * Unique item ID function + * @param sd : Player + * @return unique_id + */ +uint64 itemdb_unique_id(struct map_session_data *sd) { + return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++; } /** Check if the item is restricted by item_noequip.txt @@ -1542,7 +1503,6 @@ static void itemdb_read(void) { aFree(dbsubpath1); aFree(dbsubpath2); } - itemdb_uid_load(); } /*========================================== diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 36662a20db..67a5e76404 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -479,7 +479,7 @@ bool itemdb_isequip2(struct item_data *id); char itemdb_isidentified(unsigned short nameid); bool itemdb_isstackable2(struct item_data *id); #define itemdb_isstackable(nameid) itemdb_isstackable2(itemdb_search(nameid)) -uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID +uint64 itemdb_unique_id(struct map_session_data *sd); // Unique Item ID bool itemdb_isNoEquip(struct item_data *id, uint16 m); struct item_combo *itemdb_combo_exists(unsigned short combo_id); diff --git a/src/map/pc.c b/src/map/pc.c index f2e5896ed0..364d6a7f72 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4308,10 +4308,8 @@ char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_p sd->last_addeditem_index = i; clif_additem(sd,i,amount,0); } -#ifdef NSI_UNIQUE_ID if( !itemdb_isstackable2(id) && !item->unique_id ) - sd->status.inventory[i].unique_id = itemdb_unique_id(0,0); -#endif + sd->status.inventory[i].unique_id = itemdb_unique_id(sd); log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]); sd->weight += w; @@ -9518,12 +9516,17 @@ void pc_check_available_item(struct map_session_data *sd) { for( i = 0; i < MAX_INVENTORY; i++ ) { it = sd->status.inventory[i].nameid; - if( it && !itemdb_available(it) ) { + if (!it) + continue; + if (!itemdb_available(it)) { sprintf(output, msg_txt(sd, 709), it); // Item %hu has been removed from your inventory. clif_displaymessage(sd->fd, output); ShowWarning("Removed invalid/disabled item id %hu from inventory (amount=%d, char_id=%d).\n", it, sd->status.inventory[i].amount, sd->status.char_id); pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + continue; } + if (!sd->status.inventory[i].unique_id && !itemdb_isstackable(it)) + sd->status.inventory[i].unique_id = itemdb_unique_id(sd); } } @@ -9531,12 +9534,17 @@ void pc_check_available_item(struct map_session_data *sd) { for( i = 0; i < MAX_CART; i++ ) { it = sd->status.cart[i].nameid; - if( it && !itemdb_available(it) ) { + if (!it) + continue; + if (!itemdb_available(it)) { sprintf(output, msg_txt(sd, 710), it); // Item %hu has been removed from your cart. clif_displaymessage(sd->fd, output); ShowWarning("Removed invalid/disabled item id %hu from cart (amount=%d, char_id=%d).\n", it, sd->status.cart[i].amount, sd->status.char_id); pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); + continue; } + if (!sd->status.cart[i].unique_id && !itemdb_isstackable(it)) + sd->status.cart[i].unique_id = itemdb_unique_id(sd); } } @@ -9544,12 +9552,17 @@ void pc_check_available_item(struct map_session_data *sd) { for( i = 0; i < sd->storage_size; i++ ) { it = sd->status.storage.items[i].nameid; - if( it && !itemdb_available(it) ) { + if (!it) + continue; + if (!itemdb_available(it)) { sprintf(output, msg_txt(sd, 711), it); // Item %hu has been removed from your storage. clif_displaymessage(sd->fd, output); ShowWarning("Removed invalid/disabled item id %hu from storage (amount=%d, char_id=%d).\n", it, sd->status.storage.items[i].amount, sd->status.char_id); storage_delitem(sd, i, sd->status.storage.items[i].amount); + continue; } + if (!sd->status.storage.items[i].unique_id && !itemdb_isstackable(it)) + sd->status.storage.items[i].unique_id = itemdb_unique_id(sd); } } } diff --git a/src/map/script.c b/src/map/script.c index fdf4ef9bbd..f5aa48fb3d 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7793,6 +7793,46 @@ BUILDIN_FUNC(getequipid) return SCRIPT_CMD_SUCCESS; } +/*========================================== + * GetEquipUniqueID(Pos); Pos: 1-14 + *------------------------------------------*/ +BUILDIN_FUNC(getequipuniqueid) +{ + int i, num; + TBL_PC* sd; + struct item* item; + + sd = script_rid2sd(st); + if (sd == NULL) + return 0; + + num = script_getnum(st,2) - 1; + if (num < 0 || num >= ARRAYLENGTH(equip)) { + script_pushconststr(st, ""); + return 0; + } + + // get inventory position of item + i = pc_checkequip(sd,equip[num]); + if (i < 0) { + script_pushconststr(st, ""); + return 0; + } + + item = &sd->status.inventory[i]; + if (item != 0) { + char buf[256]; + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf)-1, "%llu", (unsigned long long)item->unique_id); + + script_pushstr(st, buf); + } else + script_pushconststr(st, ""); + + return SCRIPT_CMD_SUCCESS; +} + /*========================================== * Get the equipement name at pos * return item jname or "" @@ -19108,6 +19148,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(strcharinfo,"i"), BUILDIN_DEF(strnpcinfo,"i"), BUILDIN_DEF(getequipid,"i"), + BUILDIN_DEF(getequipuniqueid,"i"), BUILDIN_DEF(getequipname,"i"), BUILDIN_DEF(getbrokenid,"i"), // [Valaris] BUILDIN_DEF(repair,"i"), // [Valaris]