Selaa lähdekoodia

* Rework some party code.
- add leader argument to party_fill_member
- add party_getmemberid
- add requester char_id to packets 0x3021 and 0x3821 (party info)
- diff members when replacing party info
- remove fixup all-player-iteration when receiving a party for the first time
- send 'party info' before 'party created'
- send 'party info' before 'party member added'
- update empty party_id when checking the player of a party

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14968 54d463be-8e91-2dee-dedb-b68131a5f0ec

flaviojs 13 vuotta sitten
vanhempi
commit
7b1ca6d8b3
9 muutettua tiedostoa jossa 181 lisäystä ja 140 poistoa
  1. 10 0
      Changelog-Trunk.txt
  2. 21 23
      src/char/int_party.c
  3. 1 1
      src/char/inter.c
  4. 21 22
      src/char_sql/int_party.c
  5. 1 1
      src/char_sql/inter.c
  6. 10 9
      src/map/intif.c
  7. 1 1
      src/map/intif.h
  8. 112 80
      src/map/party.c
  9. 4 3
      src/map/party.h

+ 10 - 0
Changelog-Trunk.txt

@@ -1,5 +1,15 @@
 Date	Added
 
+2011/10/09
+	* Rework some party code. [FlavioJS]
+	- add leader argument to party_fill_member
+	- add party_getmemberid
+	- add requester char_id to packets 0x3021 and 0x3821 (party info)
+	- diff members when replacing party info
+	- remove fixup all-player-iteration when receiving a party for the first time
+	- send 'party info' before 'party created'
+	- send 'party info' before 'party member added'
+	- update empty party_id when checking the player of a party
 2011/10/07
 	* Remove fds from the shortlist before processing. [FlavioJS]
 2011/09/18

+ 21 - 23
src/char/int_party.c

@@ -309,29 +309,29 @@ int mapif_party_created(int fd,int account_id, int char_id, struct party *p)
 }
 
 // パ?ティ情報見つからず
-int mapif_party_noinfo(int fd, int party_id) {
-	WFIFOHEAD(fd, 8);
+static void mapif_party_noinfo(int fd, int party_id, int char_id)
+{
+	WFIFOHEAD(fd, 12);
 	WFIFOW(fd,0) = 0x3821;
-	WFIFOW(fd,2) = 8;
-	WFIFOL(fd,4) = party_id;
-	WFIFOSET(fd,8);
-	ShowWarning("int_party: info not found %d\n", party_id);
-
-	return 0;
+	WFIFOW(fd,2) = 12;
+	WFIFOL(fd,4) = char_id;
+	WFIFOL(fd,8) = party_id;
+	WFIFOSET(fd,12);
+	ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
 }
 
 // パ?ティ情報まとめ送り
-int mapif_party_info(int fd, struct party *p) {
-	unsigned char buf[2048];
-
+static void mapif_party_info(int fd, struct party* p, int char_id)
+{
+	unsigned char buf[8 + sizeof(struct party)];
 	WBUFW(buf,0) = 0x3821;
-	memcpy(buf + 4, p, sizeof(struct party));
-	WBUFW(buf,2) = 4 + sizeof(struct party);
+	WBUFW(buf,2) = 8 + sizeof(struct party);
+	WBUFL(buf,4) = char_id;
+	memcpy(WBUFP(buf,8), p, sizeof(struct party));
 	if (fd < 0)
 		mapif_sendall(buf, WBUFW(buf,2));
 	else
 		mapif_send(fd, buf, WBUFW(buf,2));
-	return 0;
 }
 
 // パ?ティメンバ追加可否
@@ -472,25 +472,23 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
 	int_party_calc_state(p);
 	idb_put(party_db, p->party.party_id, p);
 
+	mapif_party_info(fd, &p->party, 0);
 	mapif_party_created(fd, leader->account_id, leader->char_id, &p->party);
-	mapif_party_info(fd, &p->party);
 
 	return 0;
 }
 
 // パ?ティ情報要求
-int mapif_parse_PartyInfo(int fd, int party_id)
+static void mapif_parse_PartyInfo(int fd, int party_id, int char_id)
 {
 	struct party_data *p;
 
 	p = (struct party_data*)idb_get(party_db, party_id);
 	if (p != NULL)
-		mapif_party_info(fd, &p->party);
+		mapif_party_info(fd, &p->party, char_id);
 	else {
-		mapif_party_noinfo(fd, party_id);
+		mapif_party_noinfo(fd, party_id, char_id);
 	}
-
-	return 0;
 }
 
 // パーティ追加要求	
@@ -524,8 +522,8 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member
 		int_party_check_lv(p);
 	}
 
+	mapif_party_info(-1, &p->party, 0);
 	mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
-	mapif_party_info(-1, &p->party);
 
 	return 0;
 }
@@ -574,7 +572,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
 				int_party_check_lv(p);
 			}
 			if (party_check_empty(&p->party) == 0)
-				mapif_party_info(-1, &p->party);
+				mapif_party_info(-1, &p->party, 0);
 			return 0;
 		}
 	}
@@ -679,7 +677,7 @@ int inter_party_parse_frommap(int fd) {
 	RFIFOHEAD(fd);
 	switch(RFIFOW(fd,0)) {
 	case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
-	case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2)); break;
+	case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break;
 	case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
 	case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
 	case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;

+ 1 - 1
src/char/inter.c

@@ -52,7 +52,7 @@ int inter_send_packet_length[]={
 int inter_recv_packet_length[]={
 	-1,-1, 7,-1, -1,13,36, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3000-0x300f
 	 6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0, //0x3010-0x301f
-	-1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0,  0, 0,  0, 0, //0x3020-0x302f
+	-1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0,  0, 0,  0, 0, //0x3020-0x302f Party
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, //0x3030-0x303f
 	 5, 9, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3040-0x304f
 	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3050-0x305f

+ 21 - 22
src/char_sql/int_party.c

@@ -357,29 +357,29 @@ int mapif_party_created(int fd,int account_id,int char_id,struct party *p)
 }
 
 // パーティ情報見つからず
-int mapif_party_noinfo(int fd,int party_id)
+static void mapif_party_noinfo(int fd, int party_id, int char_id)
 {
-	WFIFOHEAD(fd,8);
-	WFIFOW(fd,0)=0x3821;
-	WFIFOW(fd,2)=8;
-	WFIFOL(fd,4)=party_id;
-	WFIFOSET(fd,8);
-	ShowWarning("int_party: info not found %d\n",party_id);
-	return 0;
+	WFIFOHEAD(fd, 12);
+	WFIFOW(fd,0) = 0x3821;
+	WFIFOW(fd,2) = 12;
+	WFIFOL(fd,4) = char_id;
+	WFIFOL(fd,8) = party_id;
+	WFIFOSET(fd,12);
+	ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
 }
 // パーティ情報まとめ送り
-int mapif_party_info(int fd,struct party *p)
+static void mapif_party_info(int fd, struct party* p, int char_id)
 {
-	unsigned char buf[5+sizeof(struct party)];
-	WBUFW(buf,0)=0x3821;
-	WBUFW(buf,2)=4+sizeof(struct party);
-	memcpy(buf+4,p,sizeof(struct party));
+	unsigned char buf[8 + sizeof(struct party)];
+	WBUFW(buf,0) = 0x3821;
+	WBUFW(buf,2) = 8 + sizeof(struct party);
+	WBUFL(buf,4) = char_id;
+	memcpy(WBUFP(buf,8), p, sizeof(struct party));
 
 	if(fd<0)
 		mapif_sendall(buf,WBUFW(buf,2));
 	else
 		mapif_send(fd,buf,WBUFW(buf,2));
-	return 0;
 }
 // パーティメンバ追加可否
 int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag) {
@@ -506,8 +506,8 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
 		//Add party to db
 		int_party_calc_state(p);
 		idb_put(party_db_, p->party.party_id, p);
+		mapif_party_info(fd, &p->party, 0);
 		mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
-		mapif_party_info(fd,&p->party);
 	} else { //Failed to create party.
 		aFree(p);
 		mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
@@ -516,16 +516,15 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
 	return 0;
 }
 // パーティ情報要求
-int mapif_parse_PartyInfo(int fd,int party_id)
+static void mapif_parse_PartyInfo(int fd, int party_id, int char_id)
 {
 	struct party_data *p;
 	p = inter_party_fromsql(party_id);
 
 	if (p)
-		mapif_party_info(fd,&p->party);
+		mapif_party_info(fd, &p->party, char_id);
 	else
-		mapif_party_noinfo(fd,party_id);
-	return 0;
+		mapif_party_noinfo(fd, party_id, char_id);
 }
 // パーティ追加要求
 int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member)
@@ -558,8 +557,8 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member
 		int_party_check_lv(p);
 	}
 
+	mapif_party_info(-1, &p->party, 0);
 	mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
-	mapif_party_info(-1, &p->party);
 	inter_party_tosql(&p->party, PS_ADDMEMBER, i);
 
 	return 0;
@@ -633,7 +632,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
 	}
 		
 	if (party_check_empty(p) == 0)
-		mapif_party_info(-1,&p->party);
+		mapif_party_info(-1, &p->party, 0);
 	return 0;
 }
 // When member goes to other map or levels up.
@@ -746,7 +745,7 @@ int inter_party_parse_frommap(int fd)
 	RFIFOHEAD(fd);
 	switch(RFIFOW(fd,0)) {
 	case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
-	case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2)); break;
+	case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break;
 	case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
 	case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
 	case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;

+ 1 - 1
src/char_sql/inter.c

@@ -47,7 +47,7 @@ char main_chat_nick[16] = "Main";
 int inter_recv_packet_length[] = {
 	-1,-1, 7,-1, -1,13,36, 0,  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-
-	-1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0,  0, 0,  0, 0,	// 3020-
+	-1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0,  0, 0,  0, 0,	// 3020- Party
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1,	// 3030-
 	 5, 9, 0, 0,  0, 0, 0, 0,  7, 6,10,10, 10,-1,  0, 0,	// 3040-
 	-1,-1,10,10,  0,-1, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3050-  Auction System [Zephyrus]

+ 10 - 9
src/map/intif.c

@@ -381,14 +381,15 @@ int intif_create_party(struct party_member *member,char *name,int item,int item2
 	return 0;
 }
 // パーティ情報要求
-int intif_request_partyinfo(int party_id)
+int intif_request_partyinfo(int party_id, int char_id)
 {
 	if (CheckForCharServer())
 		return 0;
-	WFIFOHEAD(inter_fd,6);
+	WFIFOHEAD(inter_fd,10);
 	WFIFOW(inter_fd,0) = 0x3021;
 	WFIFOL(inter_fd,2) = party_id;
-	WFIFOSET(inter_fd,6);
+	WFIFOL(inter_fd,6) = char_id;
+	WFIFOSET(inter_fd,10);
 	return 0;
 }
 // パーティ追加要求
@@ -1007,15 +1008,15 @@ int intif_parse_PartyCreated(int fd)
 // パーティ情報
 int intif_parse_PartyInfo(int fd)
 {
-	if( RFIFOW(fd,2)==8){
-		ShowWarning("intif: party noinfo %d\n",RFIFOL(fd,4));
-		party_recv_noinfo(RFIFOL(fd,4));
+	if( RFIFOW(fd,2) == 12 ){
+		ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8));
+		party_recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4));
 		return 0;
 	}
 
-	if( RFIFOW(fd,2)!=sizeof(struct party)+4 )
-		ShowError("intif: party info : data size error %d %d %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct party)+4);
-	party_recv_info((struct party *)RFIFOP(fd,4));
+	if( RFIFOW(fd,2) != 8+sizeof(struct party) )
+		ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party));
+	party_recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4));
 	return 0;
 }
 // パーティ追加通知

+ 1 - 1
src/map/intif.h

@@ -30,7 +30,7 @@ int intif_send_guild_storage(int account_id, struct guild_storage *gstor);
 
 
 int intif_create_party(struct party_member *member,char *name,int item,int item2);
-int intif_request_partyinfo(int party_id);
+int intif_request_partyinfo(int party_id, int char_id);
 
 int intif_party_addmember(int party_id,struct party_member *member);
 int intif_party_changeoption(int party_id, int account_id, int exp, int item);

+ 112 - 80
src/map/party.c

@@ -28,8 +28,8 @@
 #include <string.h>
 
 
-static DBMap* party_db; // int party_id -> struct party_data*
-static DBMap* party_booking_db; // Party Booking [Spiria]
+static DBMap* party_db; // int party_id -> struct party_data* (releases data)
+static DBMap* party_booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria]
 static unsigned long party_booking_nextid = 1;
 
 int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
@@ -38,18 +38,36 @@ int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
  * Fills the given party_member structure according to the sd provided. 
  * Used when creating/adding people to a party. [Skotlex]
  *------------------------------------------*/
-static void party_fill_member(struct party_member *member, struct map_session_data *sd)
+static void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader)
 {
   	member->account_id = sd->status.account_id;
 	member->char_id    = sd->status.char_id;
-	memcpy(member->name, sd->status.name, NAME_LENGTH);
+	safestrncpy(member->name, sd->status.name, NAME_LENGTH);
 	member->class_     = sd->status.class_;
 	member->map        = sd->mapindex;
 	member->lv         = sd->status.base_level;
 	member->online     = 1;
-	member->leader     = 0;
+	member->leader     = leader;
 }
 
+
+/// Get the member_id of a party member.
+/// Return -1 if not in party.
+int party_getmemberid(struct party_data* p, struct map_session_data* sd)
+{
+	int member_id;
+	nullpo_retr(-1, p);
+	if( sd == NULL )
+		return -1;// no player
+	ARR_FIND(0, MAX_PARTY, member_id,
+		p->party.member[member_id].account_id == sd->status.account_id &&
+		p->party.member[member_id].char_id == sd->status.char_id);
+	if( member_id == MAX_PARTY )
+		return -1;// not found
+	return member_id;
+}
+
+
 /*==========================================
  * Request an available sd of this party
  *------------------------------------------*/
@@ -72,6 +90,8 @@ static TBL_PC* party_sd_check(int party_id, int account_id, int char_id)
 	if (!(sd && sd->status.char_id == char_id))
 		return NULL;
 
+	if( sd->status.party_id == 0 )
+		sd->status.party_id = party_id;// auto-join if not in a party
 	if (sd->status.party_id != party_id)
 	{	//If player belongs to a different party, kick him out.
 		intif_party_leave(party_id,account_id,char_id);
@@ -143,8 +163,7 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2)
 
 	sd->party_creating = true;
 
-	party_fill_member(&leader, sd);
-	leader.leader = 1;
+	party_fill_member(&leader, sd, 1);
 
 	intif_create_party(&leader,name,item,item2);
 	return 0;
@@ -175,63 +194,26 @@ void party_created(int account_id,int char_id,int fail,int party_id,char *name)
 
 }
 
-int party_request_info(int party_id)
+int party_request_info(int party_id, int char_id)
 {
-	return intif_request_partyinfo(party_id);
+	return intif_request_partyinfo(party_id, char_id);
 }
 
-/// Checks if each char having a party actually belongs to that party.
-/// If check fails, the char gets marked as 'not in a party'.
-int party_check_member(struct party *p)
+/// Invoked (from char-server) when the party info is not found.
+int party_recv_noinfo(int party_id, int char_id)
 {
-	int i;
-	struct map_session_data *sd;
-	struct s_mapiterator* iter;
+	struct map_session_data* sd;
 
-	nullpo_ret(p);
-
-	iter = mapit_getallusers();
-	for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
+	party_broken(party_id);
+	if( char_id != 0 )// requester
 	{
-		if( sd->status.party_id != p->party_id )
-			continue;
-
-		ARR_FIND( 0, MAX_PARTY, i, p->member[i].account_id == sd->status.account_id && p->member[i].char_id == sd->status.char_id );
-		if( i == MAX_PARTY )
-		{
-			ShowWarning("party_check_member: '%s' (acc:%d) is not member of party '%s' (id:%d)\n",sd->status.name,sd->status.account_id,p->name,p->party_id);
+		sd = map_charid2sd(char_id);
+		if( sd && sd->status.party_id == party_id )
 			sd->status.party_id = 0;
-		}
 	}
-	mapit_free(iter);
-
-	return 0;
-}
-
-/// Marks all chars belonging to this party as 'not in a party'.
-int party_recv_noinfo(int party_id)
-{
-	struct map_session_data *sd;
-	struct s_mapiterator* iter;
-
-	iter = mapit_getallusers();
-	for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
-	{
-		if( sd->status.party_id == party_id )
-			sd->status.party_id = 0; // erase party
-	}
-	mapit_free(iter);
-
 	return 0;
 }
 
-static void* create_party(DBKey key, va_list args)
-{
-	struct party_data *p;
-	p=(struct party_data *)aCalloc(1,sizeof(struct party_data));
-	return p;
-}
-
 static void party_check_state(struct party_data *p)
 {
 	int i;
@@ -259,42 +241,92 @@ static void party_check_state(struct party_data *p)
 	}
 }
 
-int party_recv_info(struct party *sp)
+int party_recv_info(struct party* sp, int char_id)
 {
-	struct party_data *p;
+	struct party_data* p;
+	struct party_member* member;
+	struct map_session_data* sd;
+	int removed[MAX_PARTY];// member_id in old data
+	int removed_count = 0;
+	int added[MAX_PARTY];// member_id in new data
+	int added_count = 0;
 	int i;
-	bool party_new = false;
+	int member_id;
 	
 	nullpo_ret(sp);
 
-	p = (struct party_data*)idb_ensure(party_db, sp->party_id, create_party);
-	if (!p->party.party_id) //party just received.
+	p = (struct party_data*)idb_get(party_db, sp->party_id);
+	if( p != NULL )// diff members
+	{
+		for( member_id = 0; member_id < MAX_PARTY; ++member_id )
+		{
+			member = &p->party.member[member_id];
+			if( member->char_id == 0 )
+				continue;// empty
+			ARR_FIND(0, MAX_PARTY, i,
+				sp->member[i].account_id == member->account_id &&
+				sp->member[i].char_id == member->char_id);
+			if( i == MAX_PARTY )
+				removed[removed_count++] = member_id;
+		}
+		for( member_id = 0; member_id < MAX_PARTY; ++member_id )
+		{
+			member = &sp->member[member_id];
+			if( member->char_id == 0 )
+				continue;// empty
+			ARR_FIND(0, MAX_PARTY, i,
+				p->party.member[i].account_id == member->account_id &&
+				p->party.member[i].char_id == member->char_id);
+			if( i == MAX_PARTY )
+				added[added_count++] = member_id;
+		}
+	}
+	else
 	{
-		party_new = true;
-		party_check_member(sp);
+		for( member_id = 0; member_id < MAX_PARTY; ++member_id )
+			if( sp->member[member_id].char_id != 0 )
+				added[added_count++] = member_id;
+		CREATE(p, struct party_data, 1);
+		idb_put(party_db, sp->party_id, p);
 	}
-	memcpy(&p->party,sp,sizeof(struct party));
+	while( removed_count > 0 )// no longer in party
+	{
+		member_id = removed[--removed_count];
+		sd = p->data[member_id].sd;
+		if( sd == NULL )
+			continue;// not online
+		party_member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id);
+	}
+	memcpy(&p->party, sp, sizeof(struct party));
 	memset(&p->state, 0, sizeof(p->state));
 	memset(&p->data, 0, sizeof(p->data));
-	for(i=0;i<MAX_PARTY;i++){
-		if (!p->party.member[i].account_id)
-			continue;
-		p->data[i].sd = party_sd_check(p->party.party_id, p->party.member[i].account_id, p->party.member[i].char_id);
+	for( member_id = 0; member_id < MAX_PARTY; member_id++ )
+	{
+		member = &p->party.member[member_id];
+		if ( member->char_id == 0 )
+			continue;// empty
+		p->data[member_id].sd = party_sd_check(sp->party_id, member->account_id, member->char_id);
 	}
 	party_check_state(p);
-	if (party_new) {
-		//Send party data to all players.
-		struct map_session_data *sd;
-		for(i=0;i<MAX_PARTY;i++){
-			sd = p->data[i].sd;
-			if(!sd) continue;
-			clif_charnameupdate(sd); //Update other people's display. [Skotlex]
-			clif_party_member_info(p,sd);
-			clif_party_option(p,sd,0x100);
-			clif_party_info(p,NULL);
-		}
+	while( added_count > 0 )// new in party
+	{
+		member_id = added[--added_count];
+		sd = p->data[member_id].sd;
+		if( sd == NULL )
+			continue;// not online
+		clif_charnameupdate(sd); //Update other people's display. [Skotlex]
+		clif_party_member_info(p,sd);
+		clif_party_option(p,sd,0x100);
+		clif_party_info(p,NULL);
+		if( p->instance_id != 0 )
+			clif_instance_join(sd->fd, p->instance_id);
+	}
+	if( char_id != 0 )// requester
+	{
+		sd = map_charid2sd(char_id);
+		if( sd && sd->status.party_id == sp->party_id && party_getmemberid(p,sd) == -1 )
+			sd->status.party_id = 0;// was not in the party
 	}
-	
 	return 0;
 }
 
@@ -385,7 +417,7 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag)
 	if( flag == 1 && !sd->party_creating && !sd->party_joining )
 	{// accepted and allowed
 		sd->party_joining = true;
-		party_fill_member(&member, sd);
+		party_fill_member(&member, sd, 0);
 		intif_party_addmember(sd->party_invite, &member);
 	}
 	else
@@ -407,7 +439,7 @@ void party_member_joined(struct map_session_data *sd)
 	int i;
 	if (!p)
 	{
-		party_request_info(sd->status.party_id);
+		party_request_info(sd->status.party_id, sd->status.char_id);
 		return;
 	}
 	ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id );
@@ -460,7 +492,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
 	if (i < MAX_PARTY) {
 		//TODO: This is a hack to allow the following clif calls to send the data to the new player.
 		//The correct player data is set when party_recv_info arrives soon afterwards.
-		party_fill_member(&p->party.member[i], sd);
+		party_fill_member(&p->party.member[i], sd, 0);
 		p->data[i].sd = sd;
 	}
 

+ 4 - 3
src/map/party.h

@@ -51,11 +51,12 @@ void do_init_party(void);
 void do_final_party(void);
 struct party_data* party_search(int party_id);
 struct party_data* party_searchname(const char* str);
+int party_getmemberid(struct party_data* p, struct map_session_data* sd);
 struct map_session_data* party_getavailablesd(struct party_data *p);
 
 int party_create(struct map_session_data *sd,char *name, int item, int item2);
 void party_created(int account_id,int char_id,int fail,int party_id,char *name);
-int party_request_info(int party_id);
+int party_request_info(int party_id, int char_id);
 int party_invite(struct map_session_data *sd,struct map_session_data *tsd);
 void party_member_joined(struct map_session_data *sd);
 int party_member_added(int party_id,int account_id,int char_id,int flag);
@@ -63,8 +64,8 @@ int party_leave(struct map_session_data *sd);
 int party_removemember(struct map_session_data *sd,int account_id,char *name);
 int party_member_withdraw(int party_id,int account_id,int char_id);
 void party_reply_invite(struct map_session_data *sd,int party_id,int flag);
-int party_recv_noinfo(int party_id);
-int party_recv_info(struct party *sp);
+int party_recv_noinfo(int party_id, int char_id);
+int party_recv_info(struct party* sp, int char_id);
 int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv);
 int party_broken(int party_id);
 int party_optionchanged(int party_id,int account_id,int exp,int item,int flag);