Преглед изворни кода

Fixed #122 @accountinfo issue
* Now inter-server always asking to login-server for account info instead using direct query to `login` table. Merged from HerculesWS/Hercules@da233d5
* Inter-server packet usage: HA 0x2720 & AH 0x2721
* Additional changes from inter-server to map-server to parse the account info result with type 1 by using packet 0x3808 for clif_account_name(). Just some changes from @lighta at his old diff
* Moved some messages to char_msg.conf
* Updated inter-server packet documentation

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh пре 10 година
родитељ
комит
a212839665
12 измењених фајлова са 326 додато и 124 уклоњено
  1. 17 0
      conf/msg_conf/char_msg.conf
  2. 56 5
      doc/packet_interserv.txt
  3. 56 12
      src/char/char_logif.c
  4. 1 0
      src/char/char_logif.h
  5. 89 82
      src/char/inter.c
  6. 3 0
      src/char/inter.h
  7. 61 0
      src/login/loginchrif.c
  8. 12 7
      src/map/atcommand.c
  9. 8 11
      src/map/clif.c
  10. 2 0
      src/map/clif.h
  11. 20 5
      src/map/intif.c
  12. 1 2
      src/map/intif.h

+ 17 - 0
conf/msg_conf/char_msg.conf

@@ -128,3 +128,20 @@
 209: You have placed a higher bid.
 209: You have placed a higher bid.
 210: You have won the auction.
 210: You have won the auction.
 211: Payment for your auction!.
 211: Payment for your auction!.
+
+// @accountinfo
+212: No matches were found for your criteria, '%s'
+213: An error occured, bother your admin about it.
+214: Your query returned the following %d results, please be more specific...
+215: [AID: %d] %s | %s | Level: %d/%d | %s
+216: No account with ID '%d' was found.
+217: -- Account %d --
+218: User: %s | GM Group: %d | State: %d
+219: Password: %s (PIN:%s)
+220: ****
+221: Account e-mail: %s | Birthdate: %s
+222: Last IP: %s (%s)
+223: This user has logged in %d times, the last time was at %s
+224: -- Character Details --
+225: [Slot/CID: %d/%d] %s | %s | Level: %d/%d | %s
+226: This account doesn't have characters.

+ 56 - 5
doc/packet_interserv.txt

@@ -140,8 +140,45 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 		- Ping request from char-server
 		- Ping request from char-server
 
 
 0x2720:
 0x2720:
+	Type: HA
+	Structure: <cmd>.W <map_fd>.L <u_fd>.L <u_aid>.L <u_group>.L <account_id>.L
+	index: 0,2,6,10,14,18
+	len: 22
+	parameter:
+		- cmd : packet identification (0x2720)
+		- map_fd :
+		- u_fd :
+		- u_aid :
+		- u_group :
+		- account_id :
+	desc:
+		- 
+
 0x2721:
 0x2721:
-    free
+	Type: AH
+	Structure: <cmd>.W <map_fd>.L <u_fd>.L <u_aid>.L <account_id>.L <status>.B <password>.33B <email>.40B <last_ip>.16B <last_login>.24B <group_id>.L <logincount>.L <state>.L <password>.33B <birthdate>.11B <pincode>.?B <userid>.?B
+	index: 0,2,6,10,18,19,52,92,108,132,136,140,144,155,155+PINCODE_LENGTH
+	len: 155 + PINCODE_LENGTH + NAME_LENGTH
+	parameter:
+		- cmd : packet identification (0x2721)
+		- map_fd
+		- u_fd
+		- u_aid
+		- account_id
+		- status: 0 - Failed
+		- password
+		- email
+		- last_ip
+		- last_login
+		- group_id
+		- logincount
+		- state
+		- password
+		- birthdate
+		- pincode
+		- userid
+	desc:
+		-
 
 
 0x2722:
 0x2722:
 	Type: HA
 	Type: HA
@@ -567,15 +604,16 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 
 
 0x3007
 0x3007
 	Type: ZI
 	Type: ZI
-	Structure: <cmd>.W <u_fd>.L <aid>.L <group_lv>.L
-	index: 0,2,6,10,14
-	len: 14+NAME_LENGTH
+	Structure: <cmd>.W <u_fd>.L <aid>.L <group_lv>.L <type>.B <query>.?B
+	index: 0,2,6,10,14,15
+	len: 15+NAME_LENGTH
 	parameter:
 	parameter:
 		- cmd : packet identification (0x3007)
 		- cmd : packet identification (0x3007)
 		- u_fd
 		- u_fd
 		- aid
 		- aid
 		- group_lv
 		- group_lv
-		- query
+		- type : 0 - Full account info. 1 - Return as clif_account_name
+		- query : name or aid of player we want info
 	desc:
 	desc:
 		- Request acc info
 		- Request acc info
 
 
@@ -1449,6 +1487,19 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 	desc:
 	desc:
 		- sends a mesasge to map server (fd) to a user (u_fd) although we use fd we keep aid for safe-check
 		- sends a mesasge to map server (fd) to a user (u_fd) although we use fd we keep aid for safe-check
 
 
+0x3808
+	Type: IZ
+	Structure: <cmd>.W <u_fd>.L <aid>.L <acc_name>.?B
+	index: 0,2,6,10
+	len: variable: 10+NAME+LENGTH
+	parameter:
+		- cmd : packet identification (0x3807)
+		- u_fd
+		- aid
+		- acc_name
+	desc:
+		- Transmit the result of a account_information request from map-serv, with type 1
+
 0x3818
 0x3818
 	Type: IZ
 	Type: IZ
 	Structure: <cmd>.W <len>.W <aid>.L <guild_id>.L <flag>.B <guild_storage>.?B
 	Structure: <cmd>.W <len>.W <aid>.L <guild_id>.L <flag>.B <guild_storage>.?B

+ 56 - 12
src/char/char_logif.c

@@ -609,10 +609,52 @@ int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd) {
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+* HA 0x2720
+* Request account info to login-server
+*/
+int chlogif_req_accinfo(int fd, int u_fd, int u_aid, int u_group, int account_id, int8 type) {
+	loginif_check(-1);
+	//ShowInfo("%d request account info for %d (type %d)\n", u_aid, account_id, type);
+	WFIFOHEAD(login_fd,23);
+	WFIFOW(login_fd,0) = 0x2720;
+	WFIFOL(login_fd,2) = fd;
+	WFIFOL(login_fd,6) = u_fd;
+	WFIFOL(login_fd,10) = u_aid;
+	WFIFOL(login_fd,14) = u_group;
+	WFIFOL(login_fd,18) = account_id;
+	WFIFOB(login_fd,22) = type;
+	WFIFOSET(login_fd,23);
+	return 1;
+}
+
+/**
+ * AH 0x2721
+ * Retrieve account info from login-server, ask inter-server to tell player
+ */
+int chlogif_parse_AccInfoAck(int fd) {
+	if (RFIFOREST(fd) < 19)
+		return 0;
+	else {
+		int8 type = RFIFOB(fd, 18);
+		if (type == 0 || RFIFOREST(fd) < 155+PINCODE_LENGTH+NAME_LENGTH) {
+			mapif_accinfo_ack(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), 0, -1, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+			RFIFOSKIP(fd,19);
+			return 1;
+		}
+		type>>=1;
+		mapif_accinfo_ack(true, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), type, RFIFOL(fd,19), RFIFOL(fd,23), RFIFOL(fd,27),
+			(char*)RFIFOP(fd,31), (char*)RFIFOP(fd,71), (char*)RFIFOP(fd,87), (char*)RFIFOP(fd,111),
+			(char*)RFIFOP(fd,122), (char*)RFIFOP(fd,155), (char*)RFIFOP(fd,155+PINCODE_LENGTH));
+		RFIFOSKIP(fd,155+PINCODE_LENGTH+NAME_LENGTH);
+	}
+	return 1;
+}
+
 
 
 int chlogif_parse(int fd) {
 int chlogif_parse(int fd) {
 	struct char_session_data* sd = NULL;
 	struct char_session_data* sd = NULL;
-        
+
 	// only process data from the login-server
 	// only process data from the login-server
 	if( fd != login_fd ) {
 	if( fd != login_fd ) {
 		ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
 		ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
@@ -645,26 +687,28 @@ int chlogif_parse(int fd) {
 		uint16 command = RFIFOW(fd,0);
 		uint16 command = RFIFOW(fd,0);
 		switch( command )
 		switch( command )
 		{
 		{
-			case 0x2741: next=chlogif_parse_BankingAck(fd); break;
-			case 0x2743: next=chlogif_parse_vipack(fd); break;
+			case 0x2741: next = chlogif_parse_BankingAck(fd); break;
+			case 0x2743: next = chlogif_parse_vipack(fd); break;
 			// acknowledgement of connect-to-loginserver request
 			// acknowledgement of connect-to-loginserver request
-			case 0x2711: next=chlogif_parse_ackconnect(fd,sd); break;
+			case 0x2711: next = chlogif_parse_ackconnect(fd,sd); break;
 			// acknowledgement of account authentication request
 			// acknowledgement of account authentication request
-			case 0x2713: next=chlogif_parse_ackaccreq(fd, sd); break;
+			case 0x2713: next = chlogif_parse_ackaccreq(fd, sd); break;
 			// account data
 			// account data
-			case 0x2717: next=chlogif_parse_reqaccdata(fd, sd); break;
+			case 0x2717: next = chlogif_parse_reqaccdata(fd, sd); break;
 			// login-server alive packet
 			// login-server alive packet
-			case 0x2718: next=chlogif_parse_keepalive(fd, sd); break;
+			case 0x2718: next = chlogif_parse_keepalive(fd, sd); break;
 			// changesex reply
 			// changesex reply
-			case 0x2723: next=chlogif_parse_ackchangesex(fd, sd); break;
+			case 0x2723: next = chlogif_parse_ackchangesex(fd, sd); break;
 			// reply to an account_reg2 registry request
 			// reply to an account_reg2 registry request
-			case 0x2729: next=chlogif_parse_ackacc2req(fd, sd); break;
+			case 0x2729: next = chlogif_parse_ackacc2req(fd, sd); break;
 			// State change of account/ban notification (from login-server)
 			// State change of account/ban notification (from login-server)
-			case 0x2731: next=chlogif_parse_accbannotification(fd, sd); break;
+			case 0x2731: next = chlogif_parse_accbannotification(fd, sd); break;
 			// Login server request to kick a character out. [Skotlex]
 			// Login server request to kick a character out. [Skotlex]
-			case 0x2734: next=chlogif_parse_askkick(fd,sd); break;
+			case 0x2734: next = chlogif_parse_askkick(fd,sd); break;
 			// ip address update signal from login server
 			// ip address update signal from login server
-			case 0x2735: next=chlogif_parse_updip(fd,sd); break;
+			case 0x2735: next = chlogif_parse_updip(fd,sd); break;
+			// @accinfo result
+			case 0x2721: next = chlogif_parse_AccInfoAck(fd); break;
 			default:
 			default:
 				ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
 				ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
 				set_eof(fd);
 				set_eof(fd);

+ 1 - 0
src/char/char_logif.h

@@ -40,6 +40,7 @@ int chlogif_BankingReq(int32 account_id, int8 type, int32 data);
 int chlogif_parse_BankingAck(int fd);
 int chlogif_parse_BankingAck(int fd);
 int chlogif_parse_vipack(int fd);
 int chlogif_parse_vipack(int fd);
 int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd);
 int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd);
+int chlogif_req_accinfo(int fd, int u_fd, int u_aid, int u_group, int account_id, int8 type);
 
 
 int chlogif_parse(int fd);
 int chlogif_parse(int fd);
 
 

+ 89 - 82
src/char/inter.c

@@ -48,7 +48,7 @@ unsigned int party_share_level = 10;
 
 
 // recv. packet list
 // recv. packet list
 int inter_recv_packet_length[] = {
 int inter_recv_packet_length[] = {
-	-1,-1, 7,-1, -1,13,36, (2 + 4 + 4 + 4 + NAME_LENGTH),  0, 0, 0, 0,  0, 0,  0, 0,	// 3000-
+	-1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH),  0, 0, 0, 0,  0, 0,  0, 0,	// 3000-
 	 6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0,	// 3010-
 	 6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0,	// 3010-
 	-1,10,-1,14, 14,19, 6,-1, 14,14, 6, 0,  0, 0,  0, 0,	// 3020- Party
 	-1,10,-1,14, 14,19, 6,-1, 14,14, 6, 0,  0, 0,  0, 0,	// 3020- Party
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1,	// 3030-
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1,	// 3030-
@@ -377,15 +377,36 @@ void inter_to_fd(int fd, int u_fd, int aid, char* msg, ...) {
 
 
 	return;
 	return;
 }
 }
-/* [Dekamaster/Nightroad] */
+
+/**
+ * Transmit the result of a account_information request from map-serv, with type 1
+ * @param fd : map-serv link
+ * @param u_fd : player fd to send info to
+ * @param acc_id : id of player found
+ * @param acc_name : name of player found
+ */
+static void mapif_acc_info_ack(int fd, int u_fd, int acc_id, const char* acc_name){
+	WFIFOHEAD(fd,10 + NAME_LENGTH);
+	WFIFOW(fd,0) = 0x3808;
+	WFIFOL(fd,2) = u_fd;
+	WFIFOL(fd,6) = acc_id;
+	safestrncpy((char*)WFIFOP(fd,10),acc_name,NAME_LENGTH);
+	WFIFOSET(fd,10 + NAME_LENGTH);
+}
+
+/**
+ * Receive a account_info request from map-serv
+ * @author : [Dekamaster/Nightroad]
+ * @param fd : map-serv link
+ */
 void mapif_parse_accinfo(int fd) {
 void mapif_parse_accinfo(int fd) {
-	int u_fd = RFIFOL(fd,2), aid = RFIFOL(fd,6), castergroup = RFIFOL(fd,10);
+	int u_fd = RFIFOL(fd,2), u_aid = RFIFOL(fd,6), u_group = RFIFOL(fd,10);
+	char type= RFIFOB(fd,14);
 	char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
 	char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
-	int account_id;
+	int account_id = 0;
 	char *data;
 	char *data;
 
 
-	safestrncpy(query, (char*) RFIFOP(fd,14), NAME_LENGTH);
-
+	safestrncpy(query, (char*) RFIFOP(fd,15), NAME_LENGTH);
 	Sql_EscapeString(sql_handle, query_esq, query);
 	Sql_EscapeString(sql_handle, query_esq, query);
 
 
 	account_id = atoi(query);
 	account_id = atoi(query);
@@ -394,10 +415,10 @@ void mapif_parse_accinfo(int fd) {
 		if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", schema_config.char_db, query_esq)
 		if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", schema_config.char_db, query_esq)
 				|| Sql_NumRows(sql_handle) == 0 ) {
 				|| Sql_NumRows(sql_handle) == 0 ) {
 			if( Sql_NumRows(sql_handle) == 0 ) {
 			if( Sql_NumRows(sql_handle) == 0 ) {
-				inter_to_fd(fd, u_fd, aid, "No matches were found for your criteria, '%s'",query);
+				inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(212) ,query);
 			} else {
 			} else {
 				Sql_ShowDebug(sql_handle);
 				Sql_ShowDebug(sql_handle);
-				inter_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it.");
+				inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
 			}
 			}
 			Sql_FreeResult(sql_handle);
 			Sql_FreeResult(sql_handle);
 			return;
 			return;
@@ -407,7 +428,7 @@ void mapif_parse_accinfo(int fd) {
 				Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
 				Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
 				Sql_FreeResult(sql_handle);
 				Sql_FreeResult(sql_handle);
 			} else {// more than one, listing... [Dekamaster/Nightroad]
 			} else {// more than one, listing... [Dekamaster/Nightroad]
-				inter_to_fd(fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)Sql_NumRows(sql_handle));
+				inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(214),(int)Sql_NumRows(sql_handle));
 				while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
 				while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
 					int class_;
 					int class_;
 					short base_level, job_level, online;
 					short base_level, job_level, online;
@@ -420,7 +441,7 @@ void mapif_parse_accinfo(int fd) {
 					Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data);
 					Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data);
 					Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data);
 					Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data);
 
 
-					inter_to_fd(fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
+					inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(215), account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
 				}
 				}
 				Sql_FreeResult(sql_handle);
 				Sql_FreeResult(sql_handle);
 				return;
 				return;
@@ -428,86 +449,72 @@ void mapif_parse_accinfo(int fd) {
 		}
 		}
 	}
 	}
 
 
-	/* it will only get here if we have a single match */
-	if( account_id ) {
-		char userid[NAME_LENGTH], user_pass[NAME_LENGTH], email[40], last_ip[20], lastlogin[30], pincode[5], birthdate[11];
-		short level = -1;
-		int logincount = 0,state = 0;
-		if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `userid`, `user_pass`, `email`, `last_ip`, `group_id`, `lastlogin`, `logincount`, `state`,`pincode`,`birthdate` FROM `login` WHERE `account_id` = '%d' LIMIT 1", account_id)
-			|| Sql_NumRows(sql_handle) == 0 ) {
-			if( Sql_NumRows(sql_handle) == 0 ) {
-				inter_to_fd(fd, u_fd, aid,  "No account with ID '%d' was found.", account_id );
-			} else {
-				inter_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it.");
-				Sql_ShowDebug(sql_handle);
-			}
-		} else {
-			Sql_NextRow(sql_handle);
-			Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(userid, data, sizeof(userid));
-			Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(user_pass, data, sizeof(user_pass));
-			Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(email, data, sizeof(email));
-			Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(last_ip, data, sizeof(last_ip));
-			Sql_GetData(sql_handle, 4, &data, NULL); level = atoi(data);
-			Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(lastlogin, data, sizeof(lastlogin));
-			Sql_GetData(sql_handle, 6, &data, NULL); logincount = atoi(data);
-			Sql_GetData(sql_handle, 7, &data, NULL); state = atoi(data);
-			Sql_GetData(sql_handle, 8, &data, NULL); safestrncpy(pincode, data, sizeof(pincode));
-			Sql_GetData(sql_handle, 9, &data, NULL); safestrncpy(birthdate, data, sizeof(birthdate));
-		}
-
-		Sql_FreeResult(sql_handle);
-
-		if (level == -1)
-			return;
-
-		inter_to_fd(fd, u_fd, aid, "-- Account %d --", account_id );
-		inter_to_fd(fd, u_fd, aid, "User: %s | GM Group: %d | State: %d", userid, level, state );
-
-		if (level < castergroup) { /* only show pass if your gm level is greater than the one you're searching for */
-			if( pincode[0] != '\0' )
-				inter_to_fd(fd, u_fd, aid, "Password: %s (PIN:%s)", user_pass, pincode );
-			else
-				inter_to_fd(fd, u_fd, aid, "Password: %s", user_pass );
-		}
+	/* it will only get here if we have a single match then ask login-server to fetch the `login` record */
+	if (!account_id || chlogif_req_accinfo(fd, u_fd, u_aid, u_group, account_id, type) != 1) {
+		inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
+	}
+	return;
+}
 
 
-		inter_to_fd(fd, u_fd, aid, "Account e-mail: %s | Birthdate: %s", email, birthdate);
-		inter_to_fd(fd, u_fd, aid, "Last IP: %s (%s)", last_ip, geoip_getcountry(str2ip(last_ip)) );
-		inter_to_fd(fd, u_fd, aid, "This user has logged in %d times, the last time was at %s", logincount, lastlogin );
-		inter_to_fd(fd, u_fd, aid, "-- Character Details --" );
+/**
+ * Show account info from login-server to user
+ */
+void mapif_accinfo_ack(bool success, int map_fd, int u_fd, int u_aid, int account_id, int8 type,
+	int group_id, int logincount, int state, const char *email, const char *last_ip, const char *lastlogin,
+	const char *birthdate, const char *user_pass, const char *pincode, const char *userid)
+{
+	
+	if (map_fd <= 0 || !session_isActive(map_fd))
+		return; // check if we have a valid fd
 
 
+	if (!success) {
+		inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(216), account_id);
+		return;
+	}
 
 
-		if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `char` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", account_id, MAX_CHARS)
-				|| Sql_NumRows(sql_handle) == 0 ) {
+	if (type == 1) { //type 1 we don't want all the info [lighta] @CHECKME
+		mapif_acc_info_ack(map_fd, u_fd, account_id, userid);
+		return;
+	}
 
 
-				if( Sql_NumRows(sql_handle) == 0 )
-					inter_to_fd(fd, u_fd, aid,"This account doesn't have characters.");
-				else {
-					inter_to_fd(fd, u_fd, aid,"An error occured, bother your admin about it.");
-					Sql_ShowDebug(sql_handle);
-				}
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(217), account_id);
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(218), userid, group_id, state);
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(219), user_pass[0] != '\0' ? user_pass : msg_txt(220), pincode[0] != '\0' ? msg_txt(220) : pincode);
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(221), email, birthdate);
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(222), last_ip, geoip_getcountry(str2ip(last_ip)));
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(223), logincount, lastlogin);
+	inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(224));
 
 
-		} else {
-			while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
-				int char_id, class_;
-				short char_num, base_level, job_level, online;
-				char name[NAME_LENGTH];
-
-				Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data);
-				Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
-				Sql_GetData(sql_handle, 2, &data, NULL); char_num = atoi(data);
-				Sql_GetData(sql_handle, 3, &data, NULL); class_ = atoi(data);
-				Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data);
-				Sql_GetData(sql_handle, 5, &data, NULL); job_level = atoi(data);
-				Sql_GetData(sql_handle, 6, &data, NULL); online = atoi(data);
-
-				inter_to_fd(fd, u_fd, aid, "[Slot/CID: %d/%d] %s | %s | Level: %d/%d | %s", char_num, char_id, name, job_name(class_), base_level, job_level, online?"On":"Off");
-			}
+	if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `%s` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", schema_config.char_db, account_id, MAX_CHARS)
+		|| Sql_NumRows(sql_handle) == 0 )
+	{
+		if( Sql_NumRows(sql_handle) == 0 )
+			inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(226));
+		else {
+			inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(213));
+			Sql_ShowDebug(sql_handle);
+		}
+	} else {
+		while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
+			int char_id, class_;
+			short char_num, base_level, job_level, online;
+			char name[NAME_LENGTH];
+			char *data;
+
+			Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data);
+			Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
+			Sql_GetData(sql_handle, 2, &data, NULL); char_num = atoi(data);
+			Sql_GetData(sql_handle, 3, &data, NULL); class_ = atoi(data);
+			Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data);
+			Sql_GetData(sql_handle, 5, &data, NULL); job_level = atoi(data);
+			Sql_GetData(sql_handle, 6, &data, NULL); online = atoi(data);
+
+			inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(225), char_num, char_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
 		}
 		}
-		Sql_FreeResult(sql_handle);
 	}
 	}
-
-	return;
+	Sql_FreeResult(sql_handle);
 }
 }
+
 //--------------------------------------------------------
 //--------------------------------------------------------
 // Save registry to sql
 // Save registry to sql
 int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type)
 int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type)

+ 3 - 0
src/char/inter.h

@@ -13,6 +13,9 @@ int inter_parse_frommap(int fd);
 int inter_mapif_init(int fd);
 int inter_mapif_init(int fd);
 int mapif_send_gmaccounts(void);
 int mapif_send_gmaccounts(void);
 int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason);
 int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason);
+void mapif_accinfo_ack(bool success, int map_fd, int u_fd, int u_aid, int account_id, int8 type,
+	int group_id, int logincount, int state, const char *email, const char *last_ip, const char *lastlogin,
+	const char *birthdate, const char *user_pass, const char *pincode, const char *userid);
 
 
 int inter_log(char *fmt,...);
 int inter_log(char *fmt,...);
 
 

+ 61 - 0
src/login/loginchrif.c

@@ -825,6 +825,66 @@ int logchrif_parse_reqvipdata(int fd) {
 	return 1;
 	return 1;
 }
 }
 
 
+/**
+* IA 0x2720
+* Get account info that asked by inter/char-server
+*/
+int logchrif_parse_accinfo(int fd) {
+	if( RFIFOREST(fd) < 23 )
+		return 0;
+	else {
+		int map_fd = RFIFOL(fd, 2), u_fd = RFIFOL(fd, 6), u_aid = RFIFOL(fd, 10), u_group = RFIFOL(fd, 14), account_id = RFIFOL(fd, 18);
+		short level = -1;
+		int logincount = 0, state = 0;
+		int8 type = RFIFOB(fd, 22);
+		AccountDB* accounts = login_get_accounts_db();
+		struct mmo_account acc;
+		RFIFOSKIP(fd,23);
+
+		// Send back the result to char-server
+		if (accounts->load_num(accounts, &acc, account_id)) {
+			int len = 155 + PINCODE_LENGTH + NAME_LENGTH;
+			//ShowInfo("Found account info for %d, requested by %d\n", account_id, u_aid);
+			WFIFOHEAD(fd, len);
+			WFIFOW(fd, 0) = 0x2721;
+			WFIFOL(fd, 2) = map_fd;
+			WFIFOL(fd, 6) = u_fd;
+			WFIFOL(fd, 10) = u_aid;
+			WFIFOL(fd, 14) = account_id;
+			WFIFOB(fd, 18) = (1<<type); // success
+			WFIFOL(fd, 19) = acc.group_id;
+			WFIFOL(fd, 23) = acc.logincount;
+			WFIFOL(fd, 27) = acc.state;
+			safestrncpy((char*)WFIFOP(fd, 31), acc.email, 40);
+			safestrncpy((char*)WFIFOP(fd, 71), acc.last_ip, 16);
+			safestrncpy((char*)WFIFOP(fd, 87), acc.lastlogin, 24);
+			safestrncpy((char*)WFIFOP(fd, 111), acc.birthdate, 11);
+			if ((unsigned int)u_group >= acc.group_id) {
+				safestrncpy((char*)WFIFOP(fd, 122), acc.pass, 33);
+				safestrncpy((char*)WFIFOP(fd, 155), acc.pincode, PINCODE_LENGTH);
+			}
+			else {
+				memset(WFIFOP(fd, 122), '\0', 33);
+				memset(WFIFOP(fd, 155), '\0', PINCODE_LENGTH);
+			}
+			safestrncpy((char*)WFIFOP(fd, 155 + PINCODE_LENGTH), acc.userid, NAME_LENGTH);
+			WFIFOSET(fd, len);
+		}
+		else {
+			//ShowInfo("Cannot found account info for %d, requested by %d\n", account_id, u_aid);
+			WFIFOHEAD(fd, 19);
+			WFIFOW(fd, 0) = 0x2721;
+			WFIFOL(fd, 2) = map_fd;
+			WFIFOL(fd, 6) = u_fd;
+			WFIFOL(fd, 10) = u_aid;
+			WFIFOL(fd, 14) = account_id;
+			WFIFOB(fd, 18) = 0; // failed
+			WFIFOSET(fd, 19);
+		}
+	}
+	return 1;
+}
+
 /**
 /**
  * Entry point from char-server to log-server.
  * Entry point from char-server to log-server.
  * Function that checks incoming command, then splits it to the correct handler.
  * Function that checks incoming command, then splits it to the correct handler.
@@ -863,6 +923,7 @@ int logchrif_parse(int fd){
 		case 0x2715: next = logchrif_parse_updmail(fd, cid, ip); break;
 		case 0x2715: next = logchrif_parse_updmail(fd, cid, ip); break;
 		case 0x2716: next = logchrif_parse_reqaccdata(fd, cid, ip); break;
 		case 0x2716: next = logchrif_parse_reqaccdata(fd, cid, ip); break;
 		case 0x2719: next = logchrif_parse_keepalive(fd); break;
 		case 0x2719: next = logchrif_parse_keepalive(fd); break;
+		case 0x2720: next = logchrif_parse_accinfo(fd); break; //@accinfo from inter-server
 		case 0x2722: next = logchrif_parse_reqchangemail(fd,cid,ip); break;
 		case 0x2722: next = logchrif_parse_reqchangemail(fd,cid,ip); break;
 		case 0x2724: next = logchrif_parse_requpdaccstate(fd,cid,ip); break;
 		case 0x2724: next = logchrif_parse_requpdaccstate(fd,cid,ip); break;
 		case 0x2725: next = logchrif_parse_reqbanacc(fd,cid,ip); break;
 		case 0x2725: next = logchrif_parse_reqbanacc(fd,cid,ip); break;

+ 12 - 7
src/map/atcommand.c

@@ -8883,18 +8883,23 @@ ACMD_FUNC(mount2) {
 
 
 ACMD_FUNC(accinfo) {
 ACMD_FUNC(accinfo) {
 	char query[NAME_LENGTH];
 	char query[NAME_LENGTH];
+	char type = 0; // type = 1, get only account name
 
 
-	if (!message || !*message || strlen(message) > NAME_LENGTH ) {
+	if (!message || !*message || strlen(message) > NAME_LENGTH
+		|| ( sscanf(message, "%31s %c", query, &type) < 1))
+	{
 		clif_displaymessage(fd, msg_txt(sd,1365)); // Usage: @accinfo/@accountinfo <account_id/char name>
 		clif_displaymessage(fd, msg_txt(sd,1365)); // Usage: @accinfo/@accountinfo <account_id/char name>
 		clif_displaymessage(fd, msg_txt(sd,1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario".
 		clif_displaymessage(fd, msg_txt(sd,1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario".
 		return -1;
 		return -1;
-	}
-
-	//remove const type
-	safestrncpy(query, message, NAME_LENGTH);
-
-	intif_request_accinfo( sd->fd, sd->bl.id, pc_get_group_level(sd), query );
+	} else if (type != 0) {
+		type = type-'0'; //make it int
+		if (type != 1) {
+			clif_displaymessage(fd, "accinfo : Unknow type specified\n");
+			return -1;
+		}
+ 	}
 
 
+	intif_request_accinfo( sd->fd, sd->bl.id, pc_get_group_level(sd), query, type);
 	return 0;
 	return 0;
 }
 }
 
 

+ 8 - 11
src/map/clif.c

@@ -13291,10 +13291,8 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd)
 
 
 /// Result of request to resolve account name (ZC_ACK_ACCOUNTNAME).
 /// Result of request to resolve account name (ZC_ACK_ACCOUNTNAME).
 /// 01e0 <account id>.L <account name>.24B
 /// 01e0 <account id>.L <account name>.24B
-void clif_account_name(struct map_session_data* sd, int account_id, const char* accname)
+void clif_account_name(int fd, int account_id, const char* accname)
 {
 {
-	int fd = sd->fd;
-
 	WFIFOHEAD(fd,packet_len(0x1e0));
 	WFIFOHEAD(fd,packet_len(0x1e0));
 	WFIFOW(fd,0) = 0x1e0;
 	WFIFOW(fd,0) = 0x1e0;
 	WFIFOL(fd,2) = account_id;
 	WFIFOL(fd,2) = account_id;
@@ -13305,17 +13303,16 @@ void clif_account_name(struct map_session_data* sd, int account_id, const char*
 
 
 /// GM requesting account name (for right-click gm menu) (CZ_REQ_ACCOUNTNAME).
 /// GM requesting account name (for right-click gm menu) (CZ_REQ_ACCOUNTNAME).
 /// 01df <account id>.L
 /// 01df <account id>.L
+/// @CHECKME
 void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
 void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
 {
 {
-	if (sd->bl.type&BL_PC) { // Only show for players
-		char command[30];
-		int account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
+	char query[30];
+	int account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
 
 
-		//tmp get all display
-		safesnprintf(command,sizeof(command),"%caccinfo %d", atcommand_symbol, account_id);
-		is_atcommand(fd, sd, command, 1);
-		//clif_account_name(sd, account_id, ""); //! TODO request to login-serv
-	}
+	//tmp get all display
+	safesnprintf(query,sizeof(query),"%d", account_id);
+	intif_request_accinfo(sd->fd, sd->bl.id, pc_get_group_level(sd), query, 1);
+	//will call clif_account_name at return
 }
 }
 
 
 
 

+ 2 - 0
src/map/clif.h

@@ -887,6 +887,8 @@ void clif_crimson_marker(struct map_session_data *sd, struct block_list *bl, boo
 void clif_showscript(struct block_list* bl, const char* message);
 void clif_showscript(struct block_list* bl, const char* message);
 void clif_party_leaderchanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid);
 void clif_party_leaderchanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid);
 
 
+void clif_account_name(int fd, int account_id, const char* accname);
+
 //void clif_broadcast_obtain_special_item(); ///TODO!
 //void clif_broadcast_obtain_special_item(); ///TODO!
 
 
 #endif /* _CLIF_H_ */
 #endif /* _CLIF_H_ */

+ 20 - 5
src/map/intif.c

@@ -33,7 +33,7 @@
 #include <string.h>
 #include <string.h>
 
 
 static const int packet_len_table[]={
 static const int packet_len_table[]={
-	-1,-1,27,-1, -1, 0,37,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3800-0x380f
+	-1,-1,27,-1, -1, 0,37,-1, 10+NAME_LENGTH, 0, 0, 0,  0, 0,  0, 0, //0x3800-0x380f
 	 0, 0, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0, //0x3810
 	 0, 0, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0, //0x3810
 	39,-1,15,15, 14,19, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3820
 	39,-1,15,15, 14,19, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3820
 	10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1, //0x3830
 	10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1, //0x3830
@@ -2821,25 +2821,39 @@ int intif_parse_elemental_saved(int fd)
  * @param aid : requesting player aid
  * @param aid : requesting player aid
  * @param group_lv : requesting player lv
  * @param group_lv : requesting player lv
  * @param query : name or aid of player we want info
  * @param query : name or aid of player we want info
+ * @param type : 1 - Only return account id & userid, 0 - Full info
  * @return : 0=errur, 1=msg sent
  * @return : 0=errur, 1=msg sent
  */
  */
-int intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) {
+int intif_request_accinfo(int u_fd, int aid, int group_lv, char* query, char type) {
 
 
 	if( CheckForCharServer() )
 	if( CheckForCharServer() )
 		return 0;
 		return 0;
 	
 	
-	WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
+	WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + 1 + NAME_LENGTH);
 
 
 	WFIFOW(inter_fd,0) = 0x3007;
 	WFIFOW(inter_fd,0) = 0x3007;
 	WFIFOL(inter_fd,2) = u_fd;
 	WFIFOL(inter_fd,2) = u_fd;
 	WFIFOL(inter_fd,6) = aid;
 	WFIFOL(inter_fd,6) = aid;
 	WFIFOL(inter_fd,10) = group_lv;
 	WFIFOL(inter_fd,10) = group_lv;
-	safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH);
+	WFIFOB(inter_fd,14) = type;
+	safestrncpy((char *)WFIFOP(inter_fd,15), query, NAME_LENGTH);
 
 
-	WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
+	WFIFOSET(inter_fd,2 + 4 + 4 + 4 + 1 + NAME_LENGTH);
 	return 1;
 	return 1;
 }
 }
 
 
+/**
+ * Receive the reply of a request_accinfo with type 1
+ * @param fd : char-serv link
+ */
+void intif_parse_accinfo_ack( int fd ) {
+	char acc_name[NAME_LENGTH];
+	int u_fd = RFIFOL(fd,2);
+	int acc_id = RFIFOL(fd,6);
+	safestrncpy(acc_name, (char*)RFIFOP(fd,10), NAME_LENGTH);
+	clif_account_name(u_fd, acc_id, acc_name);
+}
+
 /**
 /**
  * Display a message from char-serv to a player
  * Display a message from char-serv to a player
  * @param fd : Char-serv link
  * @param fd : Char-serv link
@@ -2945,6 +2959,7 @@ int intif_parse(int fd)
 	case 0x3804:	intif_parse_Registers(fd); break;
 	case 0x3804:	intif_parse_Registers(fd); break;
 	case 0x3806:	intif_parse_ChangeNameOk(fd); break;
 	case 0x3806:	intif_parse_ChangeNameOk(fd); break;
 	case 0x3807:	intif_parse_MessageToFD(fd); break;
 	case 0x3807:	intif_parse_MessageToFD(fd); break;
+	case 0x3808:	intif_parse_accinfo_ack(fd); break;
 	case 0x3818:	intif_parse_LoadGuildStorage(fd); break;
 	case 0x3818:	intif_parse_LoadGuildStorage(fd); break;
 	case 0x3819:	intif_parse_SaveGuildStorage(fd); break;
 	case 0x3819:	intif_parse_SaveGuildStorage(fd); break;
 	case 0x3820:	intif_parse_PartyCreated(fd); break;
 	case 0x3820:	intif_parse_PartyCreated(fd); break;

+ 1 - 2
src/map/intif.h

@@ -106,8 +106,7 @@ int intif_elemental_request(int ele_id, int char_id);
 int intif_elemental_delete(int ele_id);
 int intif_elemental_delete(int ele_id);
 int intif_elemental_save(struct s_elemental *ele);
 int intif_elemental_save(struct s_elemental *ele);
 
 
-/* @accinfo */
-int intif_request_accinfo( int u_fd, int aid, int group_lv, char* query );
+int intif_request_accinfo(int u_fd, int aid, int group_lv, char* query, char type);
 
 
 int CheckForCharServer(void);
 int CheckForCharServer(void);