From 3ab1ada8d9f0c294851067c78a23b07ed2c39e69 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Thu, 4 Jun 2020 17:23:50 +0200 Subject: [PATCH] Removed account gender (#5006) Adds an upgrade script to change all existing entries to the respective gender in their account. Cleanup of a few strange design decisions in the character server code. Removed SEX_ACCOUNT. Thanks to @Daegaladh for his help. --- sql-files/main.sql | 2 +- sql-files/upgrades/upgrade_20200604.sql | 13 +++ src/char/char.cpp | 135 ++++++++++-------------- src/char/char.hpp | 8 +- src/char/char_clif.cpp | 70 ++++++++++-- src/char/char_mapif.cpp | 4 - src/common/mmo.hpp | 3 +- 7 files changed, 134 insertions(+), 101 deletions(-) create mode 100644 sql-files/upgrades/upgrade_20200604.sql diff --git a/sql-files/main.sql b/sql-files/main.sql index 21cdedf361..6b50c1a64e 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -252,7 +252,7 @@ CREATE TABLE IF NOT EXISTS `char` ( `unban_time` int(11) unsigned NOT NULL default '0', `font` tinyint(3) unsigned NOT NULL default '0', `uniqueitem_counter` int(11) unsigned NOT NULL default '0', - `sex` ENUM('M','F','U') NOT NULL default 'U', + `sex` ENUM('M','F') NOT NULL, `hotkey_rowshift` tinyint(3) unsigned NOT NULL default '0', `hotkey_rowshift2` tinyint(3) unsigned NOT NULL default '0', `clan_id` int(11) unsigned NOT NULL default '0', diff --git a/sql-files/upgrades/upgrade_20200604.sql b/sql-files/upgrades/upgrade_20200604.sql new file mode 100644 index 0000000000..afea0e3e1b --- /dev/null +++ b/sql-files/upgrades/upgrade_20200604.sql @@ -0,0 +1,13 @@ +UPDATE `char` `c` +INNER JOIN `login` `l` +ON `l`.`account_id` = `c`.`account_id` +SET `c`.`sex` = `l`.`sex` +WHERE + `c`.`sex` = 'U' +AND + `l`.`sex` <> 'S' +; + +ALTER TABLE `char` + MODIFY `sex` ENUM('M','F') NOT NULL +; diff --git a/src/char/char.cpp b/src/char/char.cpp index ea37316645..9d3d29c91b 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -857,42 +857,24 @@ bool char_memitemdata_from_sql(struct s_storage* p, int max, int id, enum storag * * @retval SEX_MALE if the per-character sex is male * @retval SEX_FEMALE if the per-character sex is female - * @retval SEX_ACCOUNT if the per-character sex is not defined or the current PACKETVER doesn't support it. */ -int char_mmo_gender(const struct char_session_data *sd, const struct mmo_charstatus *p, char sex) -{ +int char_mmo_gender( const struct char_session_data *sd, const struct mmo_charstatus *p, char sex ){ + switch( sex ){ #if PACKETVER >= 20141016 - (void)sd; (void)p; // Unused - switch (sex) { case 'M': return SEX_MALE; case 'F': return SEX_FEMALE; - case 'U': - default: - return SEX_ACCOUNT; - } #else - if (sex == 'M' || sex == 'F') { - if (!sd) { - // sd is not available, there isn't much we can do. Just return and print a warning. - ShowWarning("Character '%s' (CID: %d, AID: %d) has sex '%c', but PACKETVER does not support per-character sex. Defaulting to 'U'.\n", - p->name, p->char_id, p->account_id, sex); - return SEX_ACCOUNT; - } - if ((sex == 'M' && sd->sex == SEX_FEMALE) - || (sex == 'F' && sd->sex == SEX_MALE)) { - ShowWarning("Changing sex of character '%s' (CID: %d, AID: %d) to 'U' due to incompatible PACKETVER.\n", p->name, p->char_id, p->account_id); - chlogif_parse_ackchangecharsex(p->char_id, sd->sex); - } else { - ShowInfo("Resetting sex of character '%s' (CID: %d, AID: %d) to 'U' due to incompatible PACKETVER.\n", p->name, p->char_id, p->account_id); - } - if (SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `sex` = 'U' WHERE `char_id` = '%d'", schema_config.char_db, p->char_id)) { - Sql_ShowDebug(sql_handle); - } - } - return SEX_ACCOUNT; + case 'M': + case 'F': + // No matter what the database says, always return the account gender + return sd->sex; #endif + default: + ShowWarning( "Found unknown gender '%c' for character '%s' (CID: %d, AID: %d), returning account gender...\n", sex, p->name, p->char_id, p->account_id ); + return sd->sex; + } } int char_mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p); @@ -1383,22 +1365,14 @@ int char_check_char_name(char * name, char * esc_name) //----------------------------------- // Function to create a new character //----------------------------------- -#if PACKETVER >= 20120307 -#if PACKETVER >= 20151001 -int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style, short start_job, short unknown, int sex) { // TODO: Unknown byte -#else -int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style) { -#endif - int str = 1, agi = 1, vit = 1, int_ = 1, dex = 1, luk = 1; -#else -int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style) { -#endif +int char_make_new_char( struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short start_job, int sex ){ char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1]; struct point tmp_start_point[MAX_STARTPOINT]; struct startitem tmp_start_items[MAX_STARTITEM]; uint32 char_id; int flag, k, start_point_idx = rnd() % charserv_config.start_point_count; + int status_points; safestrncpy(name, name_, NAME_LENGTH); normalize_name(name,TRIM_CHARS); @@ -1413,32 +1387,51 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, i if( flag < 0 ) return flag; - //check other inputs -#if PACKETVER >= 20120307 -#if PACKETVER >= 20151001 - switch(sex) { - case SEX_FEMALE: - sex = 'F'; - break; - case SEX_MALE: - sex = 'M'; - break; - default: - sex = 'U'; - break; - } -#endif - if(slot < 0 || slot >= sd->char_slots) -#else - if((slot < 0 || slot >= sd->char_slots) // slots - || (str + agi + vit + int_ + dex + luk != 6*5 ) // stats - || (str < 1 || str > 9 || agi < 1 || agi > 9 || vit < 1 || vit > 9 || int_ < 1 || int_ > 9 || dex < 1 || dex > 9 || luk < 1 || luk > 9) // individual stat values - || (str + int_ != 10 || agi + luk != 10 || vit + dex != 10) ) // pairs -#endif -#if PACKETVER >= 20100413 + // Check inputs from the client - never trust it! + + // Check the slot + if( slot < 0 || slot >= sd->char_slots ){ return -4; // invalid slot -#else + } + + // Check gender + switch( sex ){ + case SEX_FEMALE: + sex = 'F'; + break; + case SEX_MALE: + sex = 'M'; + break; + default: + ShowWarning( "Received unsupported gender '%d'...\n", sex ); + return -2; // invalid input + } + + // Check status values +#if PACKETVER < 20120307 + // All stats together always have to add up to a total of 30 points + if( ( str + agi + vit + int_ + dex + luk ) != 30 ){ return -2; // invalid input + } + + // No status can be below 1 + if( str < 1 || agi < 1 || vit < 1 || int_ < 1 || dex < 1 || luk < 1 ){ + return -2; // invalid input + } + + // No status can be higher than 9 + if( str > 9 || agi > 9 || vit > 9 || int_ > 9 || dex > 9 || luk > 9 ){ + return -2; // invalid input + } + + // The status pairs always have to add up to a total of 10 points + if( ( str + int_ ) != 10 || ( agi + luk ) != 10 || ( vit + dex ) != 10 ){ + return -2; // invalid input + } + + status_points = 0; +#else + status_points = 48; #endif // check the number of already existing chars in this account @@ -1482,28 +1475,12 @@ int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, i #endif //Insert the new char entry to the database -#if PACKETVER >= 20151001 if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `class`, `zeny`, `status_point`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`, `sex`) VALUES (" "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%u', '%u', '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%c')", - schema_config.char_db, sd->account_id , slot, esc_name, start_job, charserv_config.start_zeny, 48, str, agi, vit, int_, dex, luk, + schema_config.char_db, sd->account_id , slot, esc_name, start_job, charserv_config.start_zeny, status_points, str, agi, vit, int_, dex, luk, (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color, mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, sex) ) -#elif PACKETVER >= 20120307 - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `status_point`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," - "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" - "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%u', '%u', '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", - schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, 48, str, agi, vit, int_, dex, luk, - (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color, - mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y) ) -#else - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," - "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" - "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%u', '%u', '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", - schema_config.char_db, sd->account_id , slot, esc_name, charserv_config.start_zeny, str, agi, vit, int_, dex, luk, - (40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color, - mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y) ) -#endif { Sql_ShowDebug(sql_handle); return -2; //No, stop the procedure! diff --git a/src/char/char.hpp b/src/char/char.hpp index c4e9b08c85..f1d8e9de39 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -306,13 +306,7 @@ void char_auth_ok(int fd, struct char_session_data *sd); void char_set_charselect(uint32 account_id); void char_read_fame_list(void); -#if PACKETVER >= 20151001 -int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style, short start_job, short unknown, int sex); -#elif PACKETVER >= 20120307 -int char_make_new_char_sql(struct char_session_data* sd, char* name_, int slot, int hair_color, int hair_style); -#else -int char_make_new_char_sql(struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style); -#endif +int char_make_new_char( struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short start_job, int sex ); void char_set_session_flag_(int account_id, int val, bool set); #define char_set_session_flag(account_id, val) ( char_set_session_flag_((account_id), (val), true) ) diff --git a/src/char/char_clif.cpp b/src/char/char_clif.cpp index ab2ba963dd..ef5f298a36 100644 --- a/src/char/char_clif.cpp +++ b/src/char/char_clif.cpp @@ -855,8 +855,6 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){ //Have to switch over to the DB instance otherwise data won't propagate [Kevin] cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); - if (cd->sex == SEX_ACCOUNT) - cd->sex = sd->sex; if (charserv_config.log_char) { char esc_name[NAME_LENGTH*2+1]; @@ -951,16 +949,72 @@ int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){ if( (charserv_config.char_new)==0 ) //turn character creation on/off [Kevin] char_id = -2; else { + char name[NAME_LENGTH]; + int str, agi, vit, int_, dex, luk; + int slot; + int hair_color; + int hair_style; + short start_job; + int sex; + #if PACKETVER >= 20151001 - char_id = char_make_new_char_sql(sd, RFIFOCP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29),RFIFOW(fd,31),RFIFOW(fd,32),RFIFOB(fd,35)); - RFIFOSKIP(fd,36); + // Sent values + safestrncpy( name, RFIFOCP( fd, 2 ), NAME_LENGTH ); + slot = RFIFOB( fd, 26 ); + hair_color = RFIFOW( fd, 27 ); + hair_style = RFIFOW( fd, 29 ); + start_job = RFIFOW( fd, 31 ); + // Unknown RFIFOW( fd, 32 ) + sex = RFIFOB( fd, 35 ); + + // Default values + str = 1; + agi = 1; + vit = 1; + int_ = 1; + dex = 1; + luk = 1; + + RFIFOSKIP( fd, 36 ); #elif PACKETVER >= 20120307 - char_id = char_make_new_char_sql(sd, RFIFOCP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29)); - RFIFOSKIP(fd,31); + // Sent values + safestrncpy( name, RFIFOCP( fd, 2 ), NAME_LENGTH ); + slot = RFIFOB( fd, 26 ); + hair_color = RFIFOW( fd, 27 ); + hair_style = RFIFOW( fd, 29 ); + + // Default values + str = 1; + agi = 1; + vit = 1; + int_ = 1; + dex = 1; + luk = 1; + start_job = JOB_NOVICE; + sex = sd->sex; + + RFIFOSKIP( fd, 31 ); #else - char_id = char_make_new_char_sql(sd, RFIFOCP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35)); - RFIFOSKIP(fd,37); + // Sent values + safestrncpy( name, RFIFOCP( fd, 2 ), NAME_LENGTH ); + str = RFIFOB( fd, 26 ); + agi = RFIFOB( fd, 27 ); + vit = RFIFOB( fd, 28 ); + int_ = RFIFOB( fd, 29 ); + dex = RFIFOB( fd, 30 ); + luk = RFIFOB( fd, 31 ); + slot = RFIFOB( fd, 32 ); + hair_color = RFIFOW( fd, 33 ); + hair_style = RFIFOW( fd, 35 ); + + // Default values + start_job = JOB_NOVICE; + sex = sd->sex; + + RFIFOSKIP( fd, 37 ); #endif + + char_id = char_make_new_char( sd, name, str, agi, vit, int_, dex, luk, slot, hair_color, hair_style, start_job, sex ); } if (char_id < 0) { diff --git a/src/char/char_mapif.cpp b/src/char/char_mapif.cpp index 00304318d5..37c9c87607 100644 --- a/src/char/char_mapif.cpp +++ b/src/char/char_mapif.cpp @@ -1013,8 +1013,6 @@ int chmapif_parse_reqauth(int fd, int id){ } if( runflag == CHARSERVER_ST_RUNNING && autotrade && cd ){ uint16 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; - if (cd->sex == SEX_ACCOUNT) - cd->sex = sex; WFIFOHEAD(fd,mmo_charstatus_len); WFIFOW(fd,0) = 0x2afd; @@ -1042,8 +1040,6 @@ int chmapif_parse_reqauth(int fd, int id){ ) {// auth ok uint16 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; - if (cd->sex == SEX_ACCOUNT) - cd->sex = sex; WFIFOHEAD(fd,mmo_charstatus_len); WFIFOW(fd,0) = 0x2afd; diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index 6a41312646..2424211ff6 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -971,8 +971,7 @@ enum e_job { enum e_sex { SEX_FEMALE = 0, SEX_MALE, - SEX_SERVER, - SEX_ACCOUNT = 99 + SEX_SERVER }; /// Item Bound Type