Fixed character rename feature (#1943)

This feature was broken for clients after 2011-11-01.
Added 2 new options for allowing it when the character is inside a party or guild.
The server now delivers the corresponding error messages if the player is inside a party or guild.
This commit is contained in:
Lemongrass3110 2017-02-15 13:06:31 +01:00 committed by GitHub
parent 2f659e419f
commit 7cf081c24b
5 changed files with 130 additions and 43 deletions

View File

@ -238,6 +238,15 @@ char_movetoused: yes
// Allow users to move characters as often as they like?
char_moves_unlimited: no
// Character renaming
// Allow users to rename a character while being in a party?
// Default: no
char_rename_party: no
// Allow users to rename a character while being in a guild?
// Default: no
char_rename_guild: no
// Should we check if sql-tables are correct on server startup ?
char_checkdb: yes

View File

@ -1247,16 +1247,31 @@ int char_rename_char_sql(struct char_session_data *sd, uint32 char_id)
if( !char_mmo_char_fromsql(char_id, &char_dat, false) ) // Only the short data is needed.
return 2;
// If the new name is exactly the same as the old one
if( !strcmp( sd->new_name, char_dat.name ) )
return 0;
if( char_dat.rename == 0 )
return 1;
if( !charserv_config.char_config.char_rename_party && char_dat.party_id ){
return 6;
}
if( !charserv_config.char_config.char_rename_guild && char_dat.guild_id ){
return 5;
}
Sql_EscapeStringLen(sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH));
// check if the char exist
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", schema_config.char_db, esc_name) )
{
Sql_ShowDebug(sql_handle);
return 4;
switch( char_check_char_name( sd->new_name, esc_name ) ){
case 0:
break;
case -1:
// character already exists
return 4;
default:
return 8;
}
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", schema_config.char_db, esc_name, --char_dat.rename, char_id) )
@ -2879,6 +2894,10 @@ bool char_config_read(const char* cfgName, bool normal){
charserv_config.char_config.char_del_option = atoi(w2);
} else if (strcmpi(w1, "char_del_restriction") == 0) {
charserv_config.char_config.char_del_restriction = atoi(w2);
} else if (strcmpi(w1, "char_rename_party") == 0) {
charserv_config.char_config.char_rename_party = (bool)config_switch(w2);
} else if (strcmpi(w1, "char_rename_guild") == 0) {
charserv_config.char_config.char_rename_guild = (bool)config_switch(w2);
} else if(strcmpi(w1,"db_path")==0) {
safestrncpy(schema_config.db_path, w2, sizeof(schema_config.db_path));
} else if (strcmpi(w1, "fame_list_alchemist") == 0) {

View File

@ -119,6 +119,8 @@ struct Char_Config {
int char_name_option; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor]
int char_del_option; // Character deletion type, email = 1, birthdate = 2 (default)
int char_del_restriction; // Character deletion restriction (0: none, 1: if the character is in a party, 2: if the character is in a guild, 3: if the character is in a party or a guild)
bool char_rename_party; // Character renaming in a party
bool char_rename_guild; // Character renaming in a guild
};
#define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex]

View File

@ -1055,29 +1055,33 @@ int chclif_parse_keepalive(int fd){
return 1;
}
// R 08fc <char ID>.l <new name>.24B
// R 028d <account ID>.l <char ID>.l <new name>.24B
int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd){
int i, cid = 0;
// Tells the client if the name was accepted or not
// 028e <result>.W (HC_ACK_IS_VALID_CHARNAME)
// result:
// 0 = name is not OK
// 1 = name is OK
void chclif_reqrename_response( int fd, struct char_session_data* sd, bool name_valid ){
WFIFOHEAD(fd, 4);
WFIFOW(fd, 0) = 0x28e;
WFIFOW(fd, 2) = name_valid;
WFIFOSET(fd, 4);
}
// Request for checking the new name on character renaming
// 028d <account ID>.l <char ID>.l <new name>.24B (CH_REQ_IS_VALID_CHARNAME)
int chclif_parse_reqrename( int fd, struct char_session_data* sd ){
int i, cid, aid;
char name[NAME_LENGTH];
char esc_name[NAME_LENGTH*2+1];
if(cmd == 0x8fc){
FIFOSD_CHECK(30)
cid =RFIFOL(fd,2);
safestrncpy(name, RFIFOCP(fd,6), NAME_LENGTH);
RFIFOSKIP(fd,30);
}
else if(cmd == 0x28d) {
int aid;
FIFOSD_CHECK(34);
aid = RFIFOL(fd,2);
cid =RFIFOL(fd,6);
safestrncpy(name, RFIFOCP(fd,10), NAME_LENGTH);
RFIFOSKIP(fd,34);
if( aid != sd->account_id )
return 1;
}
FIFOSD_CHECK(34);
aid = RFIFOL(fd,2);
cid = RFIFOL(fd,6);
safestrncpy(name, RFIFOCP(fd,10), NAME_LENGTH);
RFIFOSKIP(fd,34);
if( aid != sd->account_id )
return 1;
ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
if( i == MAX_CHARS )
@ -1090,12 +1094,10 @@ int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd){
safestrncpy(sd->new_name, name, NAME_LENGTH);
}
else
i = 0;
i = 0;
chclif_reqrename_response(fd, sd, i > 0);
WFIFOHEAD(fd, 4);
WFIFOW(fd,0) = 0x28e;
WFIFOW(fd,2) = i;
WFIFOSET(fd,4);
return 1;
}
@ -1158,13 +1160,70 @@ void chclif_block_character( int fd, struct char_session_data* sd){
}
}
// 0x28f <char_id>.L
// Sends the response to a rename request to the client.
// 0290 <result>.W (HC_ACK_CHANGE_CHARNAME)
// 08fd <result>.L (HC_ACK_CHANGE_CHARACTERNAME)
// result:
// 0: Successful
// 1: This character's name has already been changed. You cannot change a character's name more than once.
// 2: User information is not correct.
// 3: You have failed to change this character's name.
// 4: Another user is using this character name, so please select another one.
// 5: In order to change the character name, you must leave the guild.
// 6: In order to change the character name, you must leave the party.
// 7: Length exceeds the maximum size of the character name you want to change.
// 8: Name contains invalid characters. Character name change failed.
// 9: The name change is prohibited. Character name change failed.
// 10: Character name change failed, due an unknown error.
void chclif_rename_response(int fd, struct char_session_data* sd, int16 response) {
#if PACKETVER >= 20111101
WFIFOHEAD(fd, 6);
WFIFOW(fd, 0) = 0x8fd;
WFIFOL(fd, 2) = response;
WFIFOSET(fd, 6);
#else
WFIFOHEAD(fd, 4);
WFIFOW(fd, 0) = 0x290;
WFIFOW(fd, 2) = response;
WFIFOSET(fd, 4);
#endif
}
// Request to change a character name
// 028f <char_id>.L (CH_REQ_CHANGE_CHARNAME)
// 08fc <char_id>.L <new name>.24B (CH_REQ_CHANGE_CHARACTERNAME)
int chclif_parse_ackrename(int fd, struct char_session_data* sd){
// 0: Successful
// 1: This character's name has already been changed. You cannot change a character's name more than once.
// 2: User information is not correct.
// 3: You have failed to change this character's name.
// 4: Another user is using this character name, so please select another one.
#if PACKETVER >= 20111101
FIFOSD_CHECK(30)
{
int i, cid;
char name[NAME_LENGTH], esc_name[NAME_LENGTH * 2 + 1];
cid = RFIFOL(fd, 2);
safestrncpy(name, RFIFOCP(fd, 6), NAME_LENGTH);
RFIFOSKIP(fd, 30);
ARR_FIND(0, MAX_CHARS, i, sd->found_char[i] == cid);
if (i == MAX_CHARS)
return 1;
normalize_name(name, TRIM_CHARS);
Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
safestrncpy(sd->new_name, name, NAME_LENGTH);
// Start the renaming process
i = char_rename_char_sql(sd, cid);
chclif_rename_response(fd, sd, i);
// If the renaming was successful, we need to resend the characters
if( i == 0 )
chclif_mmo_char_send(fd, sd);
return 1;
}
#else
FIFOSD_CHECK(6)
{
int i;
@ -1176,12 +1235,10 @@ int chclif_parse_ackrename(int fd, struct char_session_data* sd){
return 1;
i = char_rename_char_sql(sd, cid);
WFIFOHEAD(fd, 4);
WFIFOW(fd,0) = 0x290;
WFIFOW(fd,2) = i;
WFIFOSET(fd,4);
chclif_rename_response(fd, sd, i);
}
return 1;
#endif
}
int chclif_ack_captcha(int fd){
@ -1262,9 +1319,9 @@ int chclif_parse(int fd) {
// client keep-alive packet (every 12 seconds)
case 0x187: next=chclif_parse_keepalive(fd); break;
// char rename
case 0x8fc: next=chclif_parse_reqrename(fd,sd,cmd); break; //request <date/version?>
case 0x28d: next=chclif_parse_reqrename(fd,sd,cmd); break; //request <date/version?>
case 0x28d: next=chclif_parse_reqrename(fd,sd); break; //Check new desired name
case 0x28f: next=chclif_parse_ackrename(fd,sd); break; //Confirm change name.
case 0x8fc: next=chclif_parse_ackrename(fd,sd); break; //Rename request without confirmation
// captcha
case 0x7e5: next=chclif_parse_reqcaptcha(fd); break; // captcha code request (not implemented)
case 0x7e7: next=chclif_parse_chkcaptcha(fd); break; // captcha code check (not implemented)

View File

@ -48,7 +48,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl);
int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd);
int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd);
int chclif_parse_keepalive(int fd);
int chclif_parse_reqrename(int fd, struct char_session_data* sd, int cmd);
int chclif_parse_reqrename(int fd, struct char_session_data* sd);
int chclif_parse_ackrename(int fd, struct char_session_data* sd);
int chclif_ack_captcha(int fd);
int chclif_parse_reqcaptcha(int fd);