summaryrefslogtreecommitdiff
path: root/src/map/party.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/party.c')
-rw-r--r--src/map/party.c192
1 files changed, 112 insertions, 80 deletions
diff --git a/src/map/party.c b/src/map/party.c
index 88f53bcb0..803c8d491 100644
--- a/src/map/party.c
+++ b/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;
}