Rewritten NSI_UNIQUE_ID system to get rid of the cross-database interreg dependency

- Removes the need for map-server to access the interreg table to store the last used ID.
- Login, char and map databases can now be hosted separately.
- Note: the unique_id structure has changed, and it now contains the generator character ID in its upper 32 bits.
- Now NSI_UNIQUE_ID System is enabled always

Special thanks to Haruna.
This commit is contained in:
Ibrahim Hossam 2014-04-08 20:40:12 +02:00
parent 4768082904
commit dd49dbc3e8
13 changed files with 21 additions and 101 deletions

View file

@ -111,6 +111,7 @@ CREATE TABLE IF NOT EXISTS `char` (
`char_opt` INT( 11 ) unsigned NOT NULL default '0',
`font` TINYINT( 3 ) UNSIGNED NOT NULL DEFAULT '0',
`unban_time` int(11) 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`),
@ -709,8 +710,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 `account_data`

View file

@ -0,0 +1,3 @@
#1396893866
ALTER TABLE `char` ADD COLUMN `uniqueitem_counter` bigint(20) NOT NULL AFTER `unban_time`;
INSERT INTO `sql_updates` (`timestamp`) VALUES (1396893866);

View file

@ -19,4 +19,5 @@
2014-01-04--16-47.sql
2014-01-06--17-22.sql
2014-02-19--17-57.sql
2014-03-25--23-57.sql
2014-03-25--23-57.sql
2014-04-07--22-04.sql

View file

@ -469,7 +469,8 @@ int 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->slotchange != cp->slotchange) || (p->robe != cp->robe) ||
(p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font)
(p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) ||
(p->uniqueitem_counter != cp->uniqueitem_counter )
) { //Save status
unsigned int opt = 0;
@ -485,7 +486,7 @@ int 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',`slotchange`='%d', `char_opt`='%u', `font`='%u'"
"`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
@ -496,7 +497,7 @@ int 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->slotchange,opt,p->font,
p->robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
p->account_id, p->char_id) )
{
Sql_ShowDebug(sql_handle);
@ -841,10 +842,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
for( j = 0; j < MAX_SLOTS; ++j )
StrBuf->Printf(&buf, ", '%d'", items[i].card[j]);
StrBuf->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, StrBuf->Value(&buf)) )
{
@ -982,10 +980,7 @@ int inventory_to_sql(const struct item items[], int max, int id) {
for( j = 0; j < MAX_SLOTS; ++j )
StrBuf->Printf(&buf, ", '%d'", items[i].card[j]);
StrBuf->AppendStr(&buf, ")");
updateLastUid(items[i].unique_id);// Unique Non Stackable Item ID
}
dbUpdateUid(sql_handle);
if( found && SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) {
Sql_ShowDebug(sql_handle);
@ -1130,7 +1125,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
"`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`,`slotchange`,"
"`char_opt`,`font`"
"`char_opt`,`font`,`uniqueitem_counter`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@ -1189,6 +1184,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_USHORT, &p->slotchange, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &opt, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL)
)
{
SqlStmt_ShowDebug(stmt);

View file

@ -90,10 +90,6 @@ unsigned int auction_create(struct auction_data *auction)
for( j = 0; j < MAX_SLOTS; j++ )
StrBuf->Printf(&buf, ",'%d'", auction->item.card[j]);
StrBuf->AppendStr(&buf, ")");
//Unique Non Stackable Item ID
updateLastUid(auction->item.unique_id);
dbUpdateUid(sql_handle);
stmt = SQL->StmtMalloc(sql_handle);
if( SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))

View file

@ -117,10 +117,6 @@ int mail_savemessage(struct mail_message* msg)
for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ", '%d'", msg->item.card[j]);
StrBuf->AppendStr(&buf, ")");
//Unique Non Stackable Item ID
updateLastUid(msg->item.unique_id);
dbUpdateUid(sql_handle);
// prepare and execute query
stmt = SQL->StmtMalloc(sql_handle);

View file

@ -1372,23 +1372,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

@ -29,17 +29,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_) do { \
uint64 unique_id_ = inter_chk_lastuid(0, 0); \
if (unique_id_ && SQL_ERROR == SQL->Query((handler_), "UPDATE `%s` SET `value`='%"PRIu64"' WHERE `varname`='unique_id'", interreg_db, unique_id_)) \
Sql_ShowDebug(handler_);\
} while(0)
#else
#define dbUpdateUid(handler_)
#define updateLastUid(val_)
#endif
#endif /* _CHAR_INTER_H_ */

View file

@ -435,6 +435,8 @@ struct mmo_charstatus {
unsigned short mod_exp,mod_drop,mod_death;
unsigned char font;
uint32 uniqueitem_counter;
};
typedef enum mail_status {

View file

@ -57,10 +57,6 @@
/// When uncommented the cap takes place after modifiers.
//#define HMAP_ZONE_DAMAGE_CAP_TYPE
/// 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
#define GP_BOUND_ITEMS

View file

@ -1966,44 +1966,10 @@ int itemdb_readdb_sql(const char *tablename) {
/*==========================================
* Unique item ID function
* Only one operation by once
* Flag:
* 0 return new id
* 1 set new value, checked with current value
* 2 set new value bypassing anything
* 3/other 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;
}
uint64 itemdb_unique_id(struct map_session_data *sd) {
return ++item_uid;
}
int itemdb_uid_load() {
char * uid;
if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `value` FROM `%s` WHERE `varname`='unique_id'",map->interreg_db))
Sql_ShowDebug(map->mysql_handle);
if( SQL_SUCCESS != SQL->NextRow(map->mysql_handle) ) {
ShowError("itemdb_uid_load: Unable to fetch unique_id data\n");
SQL->FreeResult(map->mysql_handle);
return -1;
}
SQL->GetData(map->mysql_handle, 0, &uid, NULL);
itemdb->unique_id(1, (uint64)strtoull(uid, NULL, 10));
SQL->FreeResult(map->mysql_handle);
return 0;
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
}
/**
@ -2057,8 +2023,7 @@ void itemdb_read(bool minimal) {
sv->readdb(map->db_path, "item_stack.txt", ',', 3, 3, -1, itemdb->read_stack);
sv->readdb(map->db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, itemdb->read_buyingstore);
sv->readdb(map->db_path, "item_nouse.txt", ',', 3, 3, -1, itemdb->read_nouse);
itemdb->uid_load();
}
/**
@ -2348,7 +2313,6 @@ void itemdb_defaults(void) {
itemdb->readdb_libconfig = itemdb_readdb_libconfig;
itemdb->readdb_sql = itemdb_readdb_sql;
itemdb->unique_id = itemdb_unique_id;
itemdb->uid_load = itemdb_uid_load;
itemdb->read = itemdb_read;
itemdb->destroy_item_data = destroy_item_data;
itemdb->final_sub = itemdb_final_sub;

View file

@ -576,8 +576,7 @@ struct itemdb_interface {
int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source);
int (*readdb_libconfig) (const char *filename);
int (*readdb_sql) (const char *tablename);
uint64 (*unique_id) (int8 flag, int64 value);
int (*uid_load) ();
uint64 (*unique_id) (struct map_session_data *sd);
void (*read) (bool minimal);
void (*destroy_item_data) (struct item_data *self, int free_self);
int (*final_sub) (DBKey key, DBData *data, va_list ap);

View file

@ -3991,10 +3991,10 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
sd->inventory_data[i] = data;
clif->additem(sd,i,amount,0);
}
#ifdef NSI_UNIQUE_ID
if( !itemdb->isstackable2(data) && !item_data->unique_id )
sd->status.inventory[i].unique_id = itemdb->unique_id(0,0);
#endif
sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]);
sd->weight += w;