* 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.
This commit is contained in:
aleos89
2014-08-22 17:52:15 -04:00
parent 402170c018
commit c0ed836e87
16 changed files with 85 additions and 113 deletions

View File

@@ -2540,7 +2540,15 @@ armor, but also don't want them to equip if after the check, you would do this:
---------------------------------------
*getequipname(<equpment slot>)
*getequipuniqueid(<equipment slot>)
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(<equipment slot>)
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.

View File

@@ -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`

View File

@@ -0,0 +1 @@
ALTER TABLE `char` ADD COLUMN `uniqueitem_counter` bigint(20) NOT NULL AFTER `font`;

View File

@@ -1,7 +1,6 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include <time.h>
#include <signal.h>
#include <stdarg.h>
@@ -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);

View File

@@ -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))

View File

@@ -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))

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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 {

View File

@@ -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

View File

@@ -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();
}
/*==========================================

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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]