فهرست منبع

Cleaned up character deletion code (#2296)

* Fixes #2271
Thanks to @Tokeiburu
Lemongrass3110 7 سال پیش
والد
کامیت
bbd42e7f12
3فایلهای تغییر یافته به همراه95 افزوده شده و 81 حذف شده
  1. 34 10
      src/char/char.cpp
  2. 11 1
      src/char/char.h
  3. 50 70
      src/char/char_clif.c

+ 34 - 10
src/char/char.cpp

@@ -1518,22 +1518,34 @@ int char_divorce_char_sql(int partner_id1, int partner_id2){
 /* Returns 0 if successful
  * 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 esc_name[NAME_LENGTH*2+1]; //Name needs be escaped.
 	uint32 account_id;
 	int party_id, guild_id, hom_id, base_level, partner_id, father_id, mother_id, elemental_id;
+	time_t delete_date;
 	char *data;
 	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);
+		return CHAR_DELETE_DATABASE;
+	}
 
 	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);
-		return -1;
+		return CHAR_DELETE_NOTFOUND;
 	}
 
 	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, 8, &data, NULL); mother_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_FreeResult(sql_handle);
 
 	//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 )
 	 || ( 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);
-			return -1;
+			return CHAR_DELETE_BASELEVEL;
 	}
 
 	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);
-		return -1;
+		return CHAR_DELETE_GUILD;
 	}
 
 	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);
-		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] */
@@ -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) )
 			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);
 
 		WBUFW(buf,0) = 0x2b25;
@@ -1699,7 +1716,14 @@ int char_delete_char_sql(uint32 char_id){
 		mapif_parse_BreakGuild(0,guild_id);
 	else if( guild_id )
 		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;
 }
 
 /**

+ 11 - 1
src/char/char.h

@@ -38,6 +38,16 @@ enum e_char_delete_restriction {
 	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 {
 	int db_use_sqldbs;
 	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_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_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_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);

+ 50 - 70
src/char/char_clif.c

@@ -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.
 /// 4 (0x71d): Deleting not yet possible time.
 /// 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.
-/// 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) {
 #if PACKETVER >= 20130000
 	if(result == 1 ){
@@ -563,10 +565,7 @@ int chclif_parse_char_delete2_accept(int fd, struct char_session_data* sd) {
 	FIFOSD_CHECK(12)
 	{
 		char birthdate[8+1];
-		uint32 char_id, i, k;
-		unsigned int base_level;
-		char* data;
-		time_t delete_date;
+		uint32 char_id;
 		char_id = RFIFOL(fd,2);
 
 		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;
 		RFIFOSKIP(fd,12);
 
-		ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == char_id );
-		if( i == MAX_CHARS )
-		{// 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
+		// Only check for birthdate
+		if (!chclif_delchar_check(sd, birthdate, CHAR_DEL_BIRTHDATE)) {
 			chclif_char_delete2_accept_ack(fd, char_id, 5);
 			return 1;
 		}
 
-		if( ( charserv_config.char_config.char_del_level > 0 && base_level >= (unsigned int)charserv_config.char_config.char_del_level )
-		|| ( charserv_config.char_config.char_del_level < 0 && base_level <= (unsigned int)(-charserv_config.char_config.char_del_level) ) )
-		{// character level config restriction
-			chclif_char_delete2_accept_ack(fd, char_id, 2);
-			return 1;
-		}
-
-		// success
-		if( char_delete_char_sql(char_id) < 0 ){
-			chclif_char_delete2_accept_ack(fd, char_id, 3);
-			return 1;
+		switch( char_delete(sd,char_id) ){
+			// success
+			case CHAR_DELETE_OK:
+				chclif_char_delete2_accept_ack(fd, char_id, 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;
 		}
-
-		// 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;
 }
@@ -993,7 +974,9 @@ int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){
  * 0x70 <ErrorCode>B HC_REFUSE_DELETECHAR
  * @param fd
  * @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){
 	WFIFOHEAD(fd,3);
@@ -1008,10 +991,9 @@ int chclif_parse_delchar(int fd,struct char_session_data* sd, int cmd){
 	else return 0;
 	{
 		char email[40];
-		int i, ch;
-		int cid = RFIFOL(fd,2);
+		uint32 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);
 		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;
 		}
 
-		// 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 */
-		if(char_delete_char_sql(cid)<0){
-			//can't delete the char
-			//either SQL error or can't delete by some CONFIG conditions
-			//del fail
-			chclif_refuse_delchar(fd,0);
-			return 1;
+		switch( char_delete(sd,cid) ){
+			case CHAR_DELETE_OK:
+				break;
+			case CHAR_DELETE_DATABASE:
+			case CHAR_DELETE_BASELEVEL:
+			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.*/
 		WFIFOHEAD(fd,2);
 		WFIFOW(fd,0) = 0x6f;