Cleaned up character deletion code (#2296)
* Fixes #2271 Thanks to @Tokeiburu
This commit is contained in:
parent
de3f924afc
commit
bbd42e7f12
@ -1518,22 +1518,34 @@ int char_divorce_char_sql(int partner_id1, int partner_id2){
|
|||||||
/* Returns 0 if successful
|
/* Returns 0 if successful
|
||||||
* Returns < 0 for error
|
* Returns < 0 for error
|
||||||
*/
|
*/
|
||||||
int char_delete_char_sql(uint32 char_id){
|
enum e_char_del_response char_delete(struct char_session_data* sd, uint32 char_id){
|
||||||
char name[NAME_LENGTH];
|
char name[NAME_LENGTH];
|
||||||
char esc_name[NAME_LENGTH*2+1]; //Name needs be escaped.
|
char esc_name[NAME_LENGTH*2+1]; //Name needs be escaped.
|
||||||
uint32 account_id;
|
uint32 account_id;
|
||||||
int party_id, guild_id, hom_id, base_level, partner_id, father_id, mother_id, elemental_id;
|
int party_id, guild_id, hom_id, base_level, partner_id, father_id, mother_id, elemental_id;
|
||||||
|
time_t delete_date;
|
||||||
char *data;
|
char *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
int i, k;
|
||||||
|
|
||||||
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id))
|
ARR_FIND(0, MAX_CHARS, i, sd->found_char[i] == char_id);
|
||||||
|
|
||||||
|
// Such a character does not exist in the account
|
||||||
|
if (i == MAX_CHARS) {
|
||||||
|
ShowInfo("Char deletion aborted: %s, Account ID: %u, Character ID: %u\n", name, sd->account_id, char_id);
|
||||||
|
return CHAR_DELETE_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id`,`delete_date` FROM `%s` WHERE `account_id`='%u' AND `char_id`='%u'", schema_config.char_db, sd->account_id, char_id)){
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
|
return CHAR_DELETE_DATABASE;
|
||||||
|
}
|
||||||
|
|
||||||
if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
|
if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
|
||||||
{
|
{
|
||||||
ShowError("delete_char_sql: Unable to fetch character data, deletion aborted.\n");
|
ShowInfo("Char deletion aborted: %s, Account ID: %u, Character ID: %u\n", name, sd->account_id, char_id);
|
||||||
Sql_FreeResult(sql_handle);
|
Sql_FreeResult(sql_handle);
|
||||||
return -1;
|
return CHAR_DELETE_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sql_GetData(sql_handle, 0, &data, &len); safestrncpy(name, data, NAME_LENGTH);
|
Sql_GetData(sql_handle, 0, &data, &len); safestrncpy(name, data, NAME_LENGTH);
|
||||||
@ -1546,29 +1558,34 @@ int char_delete_char_sql(uint32 char_id){
|
|||||||
Sql_GetData(sql_handle, 7, &data, NULL); father_id = atoi(data);
|
Sql_GetData(sql_handle, 7, &data, NULL); father_id = atoi(data);
|
||||||
Sql_GetData(sql_handle, 8, &data, NULL); mother_id = atoi(data);
|
Sql_GetData(sql_handle, 8, &data, NULL); mother_id = atoi(data);
|
||||||
Sql_GetData(sql_handle, 9, &data, NULL); elemental_id = atoi(data);
|
Sql_GetData(sql_handle, 9, &data, NULL); elemental_id = atoi(data);
|
||||||
|
Sql_GetData(sql_handle,10, &data, NULL); delete_date = strtoul(data, NULL, 10);
|
||||||
|
|
||||||
Sql_EscapeStringLen(sql_handle, esc_name, name, zmin(len, NAME_LENGTH));
|
Sql_EscapeStringLen(sql_handle, esc_name, name, zmin(len, NAME_LENGTH));
|
||||||
Sql_FreeResult(sql_handle);
|
Sql_FreeResult(sql_handle);
|
||||||
|
|
||||||
//check for config char del condition [Lupus]
|
//check for config char del condition [Lupus]
|
||||||
// TODO: Move this out to packet processing (0x68/0x1fb).
|
|
||||||
if( ( charserv_config.char_config.char_del_level > 0 && base_level >= charserv_config.char_config.char_del_level )
|
if( ( charserv_config.char_config.char_del_level > 0 && base_level >= charserv_config.char_config.char_del_level )
|
||||||
|| ( charserv_config.char_config.char_del_level < 0 && base_level <= -charserv_config.char_config.char_del_level )
|
|| ( charserv_config.char_config.char_del_level < 0 && base_level <= -charserv_config.char_config.char_del_level )
|
||||||
) {
|
) {
|
||||||
ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n", name, base_level);
|
ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n", name, base_level);
|
||||||
return -1;
|
return CHAR_DELETE_BASELEVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_GUILD && guild_id) // character is in guild
|
if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_GUILD && guild_id) // character is in guild
|
||||||
{
|
{
|
||||||
ShowInfo("Char deletion aborted: %s, Guild ID: %i\n", name, guild_id);
|
ShowInfo("Char deletion aborted: %s, Guild ID: %i\n", name, guild_id);
|
||||||
return -1;
|
return CHAR_DELETE_GUILD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_PARTY && party_id) // character is in party
|
if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_PARTY && party_id) // character is in party
|
||||||
{
|
{
|
||||||
ShowInfo("Char deletion aborted: %s, Party ID: %i\n", name, party_id);
|
ShowInfo("Char deletion aborted: %s, Party ID: %i\n", name, party_id);
|
||||||
return -1;
|
return CHAR_DELETE_PARTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( charserv_config.char_config.char_del_delay > 0 && ( !delete_date || delete_date > time(NULL) ) ){ // not queued or delay not yet passed
|
||||||
|
ShowInfo("Char deletion aborted: %s, Time was not set or has not been reached ye\n", name );
|
||||||
|
return CHAR_DELETE_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Divorce [Wizputer] */
|
/* Divorce [Wizputer] */
|
||||||
@ -1582,7 +1599,7 @@ int char_delete_char_sql(uint32 char_id){
|
|||||||
|
|
||||||
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", schema_config.char_db, father_id, mother_id) )
|
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", schema_config.char_db, father_id, mother_id) )
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", schema_config.skill_db, father_id, mother_id) )
|
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410' AND (`char_id`='%d' OR `char_id`='%d')", schema_config.skill_db, father_id, mother_id) )
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
|
|
||||||
WBUFW(buf,0) = 0x2b25;
|
WBUFW(buf,0) = 0x2b25;
|
||||||
@ -1699,7 +1716,14 @@ int char_delete_char_sql(uint32 char_id){
|
|||||||
mapif_parse_BreakGuild(0,guild_id);
|
mapif_parse_BreakGuild(0,guild_id);
|
||||||
else if( guild_id )
|
else if( guild_id )
|
||||||
inter_guild_leave(guild_id, account_id, char_id);// Leave your guild.
|
inter_guild_leave(guild_id, account_id, char_id);// Leave your guild.
|
||||||
return 0;
|
|
||||||
|
// refresh character list cache
|
||||||
|
for(k = i; k < MAX_CHARS-1; k++){
|
||||||
|
sd->found_char[k] = sd->found_char[k+1];
|
||||||
|
}
|
||||||
|
sd->found_char[MAX_CHARS-1] = -1;
|
||||||
|
|
||||||
|
return CHAR_DELETE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,6 +38,16 @@ enum e_char_delete_restriction {
|
|||||||
CHAR_DEL_RESTRICT_ALL
|
CHAR_DEL_RESTRICT_ALL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum e_char_del_response {
|
||||||
|
CHAR_DELETE_OK = 0,
|
||||||
|
CHAR_DELETE_DATABASE,
|
||||||
|
CHAR_DELETE_NOTFOUND,
|
||||||
|
CHAR_DELETE_BASELEVEL,
|
||||||
|
CHAR_DELETE_GUILD,
|
||||||
|
CHAR_DELETE_PARTY,
|
||||||
|
CHAR_DELETE_TIME,
|
||||||
|
};
|
||||||
|
|
||||||
struct Schema_Config {
|
struct Schema_Config {
|
||||||
int db_use_sqldbs;
|
int db_use_sqldbs;
|
||||||
char db_path[1024];
|
char db_path[1024];
|
||||||
@ -272,7 +282,7 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p);
|
|||||||
int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p);
|
int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p);
|
||||||
int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything);
|
int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything);
|
||||||
int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf);
|
int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf);
|
||||||
int char_delete_char_sql(uint32 char_id);
|
enum e_char_del_response char_delete(struct char_session_data* sd, uint32 char_id);
|
||||||
int char_rename_char_sql(struct char_session_data *sd, uint32 char_id);
|
int char_rename_char_sql(struct char_session_data *sd, uint32 char_id);
|
||||||
int char_divorce_char_sql(int partner_id1, int partner_id2);
|
int char_divorce_char_sql(int partner_id1, int partner_id2);
|
||||||
int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch, uint8 stor_id);
|
int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch, uint8 stor_id);
|
||||||
|
@ -437,8 +437,10 @@ void chclif_char_delete2_ack(int fd, uint32 char_id, uint32 result, time_t delet
|
|||||||
/// 3 (0x719): A database error occurred.
|
/// 3 (0x719): A database error occurred.
|
||||||
/// 4 (0x71d): Deleting not yet possible time.
|
/// 4 (0x71d): Deleting not yet possible time.
|
||||||
/// 5 (0x71e): Date of birth do not match.
|
/// 5 (0x71e): Date of birth do not match.
|
||||||
|
/// 6 Name does not match.
|
||||||
|
/// 7 Character Deletion has failed because you have entered an incorrect e-mail address.
|
||||||
/// Any (0x718): An unknown error has occurred.
|
/// Any (0x718): An unknown error has occurred.
|
||||||
/// HC: <082a>.W <char id>.L <Msg:0-5>.L
|
/// HC: <082a>.W <char id>.L <Msg>.L
|
||||||
void chclif_char_delete2_accept_ack(int fd, uint32 char_id, uint32 result) {
|
void chclif_char_delete2_accept_ack(int fd, uint32 char_id, uint32 result) {
|
||||||
#if PACKETVER >= 20130000
|
#if PACKETVER >= 20130000
|
||||||
if(result == 1 ){
|
if(result == 1 ){
|
||||||
@ -563,10 +565,7 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) {
|
|||||||
FIFOSD_CHECK(12)
|
FIFOSD_CHECK(12)
|
||||||
{
|
{
|
||||||
char birthdate[8+1];
|
char birthdate[8+1];
|
||||||
uint32 char_id, i, k;
|
uint32 char_id;
|
||||||
unsigned int base_level;
|
|
||||||
char* data;
|
|
||||||
time_t delete_date;
|
|
||||||
char_id = RFIFOL(fd,2);
|
char_id = RFIFOL(fd,2);
|
||||||
|
|
||||||
ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
|
ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, char_id);
|
||||||
@ -583,54 +582,36 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) {
|
|||||||
birthdate[8] = 0;
|
birthdate[8] = 0;
|
||||||
RFIFOSKIP(fd,12);
|
RFIFOSKIP(fd,12);
|
||||||
|
|
||||||
ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
|
// Only check for birthdate
|
||||||
if( i == MAX_CHARS )
|
if (!chclif_delchar_check(sd, birthdate, CHAR_DEL_BIRTHDATE)) {
|
||||||
{// character not found
|
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 3);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) )
|
|
||||||
{// data error
|
|
||||||
Sql_ShowDebug(sql_handle);
|
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 3);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10);
|
|
||||||
Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10);
|
|
||||||
|
|
||||||
if( !delete_date || delete_date>time(NULL) )
|
|
||||||
{// not queued or delay not yet passed
|
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 4);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!chclif_delchar_check(sd, birthdate, CHAR_DEL_BIRTHDATE)) { // Only check for birthdate
|
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 5);
|
chclif_char_delete2_accept_ack(fd, char_id, 5);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level )
|
switch( char_delete(sd,char_id) ){
|
||||||
|| ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) )
|
// success
|
||||||
{// character level config restriction
|
case CHAR_DELETE_OK:
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 2);
|
chclif_char_delete2_accept_ack(fd, char_id, 1);
|
||||||
return 1;
|
break;
|
||||||
|
// data error
|
||||||
|
case CHAR_DELETE_DATABASE:
|
||||||
|
// character not found
|
||||||
|
case CHAR_DELETE_NOTFOUND:
|
||||||
|
chclif_char_delete2_accept_ack(fd, char_id, 3);
|
||||||
|
break;
|
||||||
|
// in a party
|
||||||
|
case CHAR_DELETE_PARTY:
|
||||||
|
// in a guild
|
||||||
|
case CHAR_DELETE_GUILD:
|
||||||
|
// character level config restriction
|
||||||
|
case CHAR_DELETE_BASELEVEL:
|
||||||
|
chclif_char_delete2_accept_ack(fd, char_id, 2);
|
||||||
|
break;
|
||||||
|
// not queued or delay not yet passed
|
||||||
|
case CHAR_DELETE_TIME:
|
||||||
|
chclif_char_delete2_accept_ack(fd, char_id, 4);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// success
|
|
||||||
if( char_delete_char_sql(char_id) < 0 ){
|
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 3);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// refresh character list cache
|
|
||||||
for(k = i; k < MAX_CHARS-1; k++){
|
|
||||||
sd->found_char[k] = sd->found_char[k+1];
|
|
||||||
}
|
|
||||||
sd->found_char[MAX_CHARS-1] = -1;
|
|
||||||
|
|
||||||
chclif_char_delete2_accept_ack(fd, char_id, 1);
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -993,7 +974,9 @@ int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){
|
|||||||
* 0x70 <ErrorCode>B HC_REFUSE_DELETECHAR
|
* 0x70 <ErrorCode>B HC_REFUSE_DELETECHAR
|
||||||
* @param fd
|
* @param fd
|
||||||
* @param ErrorCode
|
* @param ErrorCode
|
||||||
* 00 = Incorrect Email address
|
* 00 = Incorrect Email address
|
||||||
|
* 01 = Invalid Slot
|
||||||
|
* 02 = In a party or guild
|
||||||
*/
|
*/
|
||||||
void chclif_refuse_delchar(int fd, uint8 errCode){
|
void chclif_refuse_delchar(int fd, uint8 errCode){
|
||||||
WFIFOHEAD(fd,3);
|
WFIFOHEAD(fd,3);
|
||||||
@ -1008,10 +991,9 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){
|
|||||||
else return 0;
|
else return 0;
|
||||||
{
|
{
|
||||||
char email[40];
|
char email[40];
|
||||||
int i, ch;
|
uint32 cid = RFIFOL(fd,2);
|
||||||
int cid = RFIFOL(fd,2);
|
|
||||||
|
|
||||||
ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
|
ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%u (%u)"CL_RESET"\n", sd->account_id, cid);
|
||||||
memcpy(email, RFIFOP(fd,6), 40);
|
memcpy(email, RFIFOP(fd,6), 40);
|
||||||
RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
|
RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
|
||||||
|
|
||||||
@ -1020,26 +1002,24 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if this char exists
|
|
||||||
ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid );
|
|
||||||
if( i == MAX_CHARS ) { // Such a character does not exist in the account
|
|
||||||
chclif_refuse_delchar(fd,0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove char from list and compact it
|
|
||||||
for(ch = i; ch < MAX_CHARS-1; ch++)
|
|
||||||
sd->found_char[ch] = sd->found_char[ch+1];
|
|
||||||
sd->found_char[MAX_CHARS-1] = -1;
|
|
||||||
|
|
||||||
/* Delete character */
|
/* Delete character */
|
||||||
if(char_delete_char_sql(cid)<0){
|
switch( char_delete(sd,cid) ){
|
||||||
//can't delete the char
|
case CHAR_DELETE_OK:
|
||||||
//either SQL error or can't delete by some CONFIG conditions
|
break;
|
||||||
//del fail
|
case CHAR_DELETE_DATABASE:
|
||||||
chclif_refuse_delchar(fd,0);
|
case CHAR_DELETE_BASELEVEL:
|
||||||
return 1;
|
case CHAR_DELETE_TIME:
|
||||||
|
chclif_refuse_delchar(fd, 0);
|
||||||
|
return 1;
|
||||||
|
case CHAR_DELETE_NOTFOUND:
|
||||||
|
chclif_refuse_delchar(fd, 1);
|
||||||
|
return 1;
|
||||||
|
case CHAR_DELETE_GUILD:
|
||||||
|
case CHAR_DELETE_PARTY:
|
||||||
|
chclif_refuse_delchar(fd, 2);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Char successfully deleted.*/
|
/* Char successfully deleted.*/
|
||||||
WFIFOHEAD(fd,2);
|
WFIFOHEAD(fd,2);
|
||||||
WFIFOW(fd,0) = 0x6f;
|
WFIFOW(fd,0) = 0x6f;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user