diff options
Diffstat (limited to 'src/char/int_party.c')
-rw-r--r-- | src/char/int_party.c | 761 |
1 files changed, 457 insertions, 304 deletions
diff --git a/src/char/int_party.c b/src/char/int_party.c index 2ae9e5319..7d0dd0b75 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -3,11 +3,13 @@ #include "../common/cbasetypes.h" #include "../common/mmo.h" +#include "../common/db.h" #include "../common/malloc.h" +#include "../common/strlib.h" #include "../common/socket.h" -#include "../common/db.h" -#include "../common/lock.h" #include "../common/showmsg.h" +#include "../common/mapindex.h" +#include "../common/sql.h" #include "char.h" #include "inter.h" #include "int_party.h" @@ -16,8 +18,6 @@ #include <stdlib.h> #include <string.h> -char party_txt[1024] = "save/party.txt"; -#ifndef TXT_SQL_CONVERT struct party_data { struct party party; unsigned int min_lv, max_lv; @@ -25,11 +25,11 @@ struct party_data { unsigned char size; //Total size of party. }; -static DBMap* party_db; // int party_id -> struct party_data* -static int party_newid = 100; +static struct party_data *party_pt; +static DBMap* party_db_; // int party_id -> struct party_data* -int mapif_party_broken(int party_id, int flag); -int party_check_empty(struct party *p); +int mapif_party_broken(int party_id,int flag); +int party_check_empty(struct party_data *p); int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id); int party_check_exp_share(struct party_data *p); int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag); @@ -41,7 +41,10 @@ static int int_party_check_lv(struct party_data *p) { p->min_lv = UINT_MAX; p->max_lv = 0; for(i=0;i<MAX_PARTY;i++){ - if(!p->party.member[i].online) + /** + * - If not online OR if it's a family party and this is the child (doesn't affect exp range) + **/ + if(!p->party.member[i].online || p->party.member[i].char_id == p->family ) continue; lv=p->party.member[i].lv; @@ -56,7 +59,6 @@ static int int_party_check_lv(struct party_data *p) { } return 1; } - //Calculates the state of a party. static void int_party_calc_state(struct party_data *p) { @@ -68,14 +70,20 @@ static void int_party_calc_state(struct party_data *p) p->size = p->family = 0; - //Check party size. + //Check party size for(i=0;i<MAX_PARTY;i++){ if (!p->party.member[i].lv) continue; p->size++; if(p->party.member[i].online) p->party.count++; } - if(p->size == 3) { + if( p->size == 2 && ( char_child(p->party.member[0].char_id,p->party.member[1].char_id) || char_child(p->party.member[1].char_id,p->party.member[0].char_id) ) ) { + //Child should be able to share with either of their parents [RoM] + if(p->party.member[0].class_&0x2000) //first slot is the child? + p->family = p->party.member[0].char_id; + else + p->family = p->party.member[1].char_id; + } else if( p->size == 3 ) { //Check Family State. p->family = char_family( p->party.member[0].char_id, @@ -103,212 +111,244 @@ static void int_party_calc_state(struct party_data *p) return; } -// パ?ティデ?タの文字列への?換 -int inter_party_tostr(char *str, struct party *p) { - int i, len; +// Save party to mysql +int inter_party_tosql(struct party *p, int flag, int index) +{ + // 'party' ('party_id','name','exp','item','leader_id','leader_char') + char esc_name[NAME_LENGTH*2+1];// escaped party name + int party_id; - len = sprintf(str, "%d\t%s\t%d,%d\t", p->party_id, p->name, p->exp, p->item); - for(i = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->member[i]; - len += sprintf(str + len, "%d,%d,%d\t", m->account_id, m->char_id, m->leader); - } + if( p == NULL || p->party_id == 0 ) + return 0; + party_id = p->party_id; - return 0; -} -#endif //TXT_SQL_CONVERT -// パ?ティデ?タの文字列からの?換 -int inter_party_fromstr(char *str, struct party *p) { - int i, j; - int tmp_int[16]; - char tmp_str[256]; -#ifndef TXT_SQL_CONVERT - struct mmo_charstatus* status; +#ifdef NOISY + ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name); #endif - - memset(p, 0, sizeof(struct party)); - - if (sscanf(str, "%d\t%255[^\t]\t%d,%d\t", &tmp_int[0], tmp_str, &tmp_int[1], &tmp_int[2]) != 4) + Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + + if( flag & PS_BREAK ) + {// Break the party + // we'll skip name-checking and just reset everyone with the same party id [celest] + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + Sql_ShowDebug(sql_handle); + //Remove from memory + idb_remove(party_db_, party_id); return 1; + } - p->party_id = tmp_int[0]; - memcpy(p->name, tmp_str, NAME_LENGTH); - p->exp = tmp_int[1]?1:0; - p->item = tmp_int[2]; - - for(j = 0; j < 3 && str != NULL; j++) - str = strchr(str + 1, '\t'); - - for(i = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->member[i]; - if (str == NULL) - return 1; + if( flag & PS_CREATE ) + {// Create party + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " + "(`name`, `exp`, `item`, `leader_id`, `leader_char`) " + "VALUES ('%s', '%d', '%d', '%d', '%d')", + party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) + { + Sql_ShowDebug(sql_handle); + return 0; + } + party_id = p->party_id = (int)Sql_LastInsertId(sql_handle); + } - if (sscanf(str + 1, "%d,%d,%d\t", &tmp_int[0], &tmp_int[1], &tmp_int[2]) != 3) - return 1; + if( flag & PS_BASIC ) + {// Update party info. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", + party_db, esc_name, p->exp, p->item, party_id) ) + Sql_ShowDebug(sql_handle); + } - m->account_id = tmp_int[0]; - m->char_id = tmp_int[1]; - m->leader = tmp_int[2]?1:0; + if( flag & PS_LEADER ) + {// Update leader + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", + party_db, p->member[index].account_id, p->member[index].char_id, party_id) ) + Sql_ShowDebug(sql_handle); + } + + if( flag & PS_ADDMEMBER ) + {// Add one party member. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", + char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) + Sql_ShowDebug(sql_handle); + } - str = strchr(str + 1, '\t'); -#ifndef TXT_SQL_CONVERT - if (!m->account_id) continue; - //Lookup player for rest of data. - status = search_character(m->account_id, m->char_id); - if (!status) continue; - - memcpy(m->name, status->name, NAME_LENGTH); - m->class_ = status->class_; - m->map = status->last_point.map; - m->lv = status->base_level; -#endif //TXT_SQL_CONVERT + if( flag & PS_DELMEMBER ) + {// Remove one party member. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", + char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) + Sql_ShowDebug(sql_handle); } - return 0; + if( save_log ) + ShowInfo("Party Saved (%d - %s)\n", party_id, p->name); + return 1; } -#ifndef TXT_SQL_CONVERT -// パ?ティデ?タのロ?ド -int inter_party_init() { - char line[8192]; - struct party_data *p; - FILE *fp; - int c = 0; - int i, j; - party_db = idb_alloc(DB_OPT_RELEASE_DATA); +// Read party from mysql +struct party_data *inter_party_fromsql(int party_id) +{ + int leader_id = 0; + int leader_char = 0; + struct party_data* p; + struct party_member* m; + char* data; + size_t len; + int i; - if ((fp = fopen(party_txt, "r")) == NULL) - return 1; +#ifdef NOISY + ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id); +#endif + if( party_id <= 0 ) + return NULL; + + //Load from memory + p = (struct party_data*)idb_get(party_db_, party_id); + if( p != NULL ) + return p; - while(fgets(line, sizeof(line), fp)) - { - j = 0; - if (sscanf(line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0 && party_newid <= i) { - party_newid = i; - continue; - } + p = party_pt; + memset(p, 0, sizeof(struct party_data)); - p = (struct party_data*)aCalloc(sizeof(struct party_data), 1); - if (p == NULL){ - ShowFatalError("int_party: out of memory!\n"); - exit(EXIT_FAILURE); - } - memset(p, 0, sizeof(struct party_data)); - if (inter_party_fromstr(line, &p->party) == 0 && p->party.party_id > 0) { - int_party_calc_state(p); - if (p->party.party_id >= party_newid) - party_newid = p->party.party_id + 1; - idb_put(party_db, p->party.party_id, p); - party_check_empty(&p->party); - } else { - ShowError("int_party: broken data [%s] line %d\n", party_txt, c + 1); - aFree(p); - } - c++; + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + { + Sql_ShowDebug(sql_handle); + return NULL; } - fclose(fp); - return 0; -} + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + return NULL; -void inter_party_final() -{ - party_db->destroy(party_db, NULL); - return; -} + p->party.party_id = party_id; + Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0); + Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data); + Sql_FreeResult(sql_handle); -// パ?ティ?デ?タのセ?ブ用 -int inter_party_save_sub(DBKey key, void *data, va_list ap) { - char line[8192]; - FILE *fp; + // Load members + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) ) + { + Sql_ShowDebug(sql_handle); + return NULL; + } + for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + m = &p->party.member[i]; + Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data); + Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0); + Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); + m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0); + } + Sql_FreeResult(sql_handle); + + if( save_log ) + ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name); + //Add party to memory. + CREATE(p, struct party_data, 1); + memcpy(p, party_pt, sizeof(struct party_data)); + //init state + int_party_calc_state(p); + idb_put(party_db_, party_id, p); + return p; +} - inter_party_tostr(line, &((struct party_data*)data)->party); - fp = va_arg(ap, FILE *); - fprintf(fp, "%s\n", line); +int inter_party_sql_init(void) +{ + //memory alloc + party_db_ = idb_alloc(DB_OPT_RELEASE_DATA); + party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1); + if (!party_pt) { + ShowFatalError("inter_party_sql_init: Out of Memory!\n"); + exit(EXIT_FAILURE); + } + /* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex] + ShowStatus("cleaning party table...\n"); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL", + party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) ) + Sql_ShowDebug(sql_handle); + */ return 0; } -// パ?ティ?デ?タのセ?ブ -int inter_party_save() { - FILE *fp; - int lock; - - if ((fp = lock_fopen(party_txt, &lock)) == NULL) { - ShowError("int_party: can't write [%s] !!! data is lost !!!\n", party_txt); - return 1; - } - party_db->foreach(party_db, inter_party_save_sub, fp); - lock_fclose(fp,party_txt, &lock); - return 0; +void inter_party_sql_final(void) +{ + party_db_->destroy(party_db_, NULL); + aFree(party_pt); + return; } // Search for the party according to its name -struct party_data* search_partyname(char *str) +struct party_data* search_partyname(char* str) { - struct DBIterator* iter; - struct party_data* p; - struct party_data* result = NULL; - - iter = party_db->iterator(party_db); - for( p = (struct party_data*)iter->first(iter,NULL); iter->exists(iter); p = (struct party_data*)iter->next(iter,NULL) ) + char esc_name[NAME_LENGTH*2+1]; + char* data; + struct party_data* p = NULL; + + Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) ) + Sql_ShowDebug(sql_handle); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { - if( strncmpi(p->party.name, str, NAME_LENGTH) == 0 ) - { - result = p; - break; - } + Sql_GetData(sql_handle, 0, &data, NULL); + p = inter_party_fromsql(atoi(data)); } - iter->destroy(iter); + Sql_FreeResult(sql_handle); - return result; + return p; } // Returns whether this party can keep having exp share or not. -int party_check_exp_share(struct party_data *p) { - return (p->party.count < 2|| p->max_lv - p->min_lv <= party_share_level); +int party_check_exp_share(struct party_data *p) +{ + return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level); } -// パ?ティが空かどうかチェック -int party_check_empty(struct party *p) { +// Is there any member in the party? +int party_check_empty(struct party_data *p) +{ int i; - - for(i = 0; i < MAX_PARTY; i++) { - if (p->member[i].account_id > 0) { - return 0; - } - } - mapif_party_broken(p->party_id, 0); - idb_remove(party_db, p->party_id); - + if (p==NULL||p->party.party_id==0) return 1; + for(i=0;i<MAX_PARTY && !p->party.member[i].account_id;i++); + if (i < MAX_PARTY) return 0; + // If there is no member, then break the party + mapif_party_broken(p->party.party_id,0); + inter_party_tosql(&p->party, PS_BREAK, 0); return 1; } //------------------------------------------------------------------- // map serverへの通信 -// パ?ティ作成可否 -int mapif_party_created(int fd,int account_id, int char_id, struct party *p) +// パーティ作成可否 +int mapif_party_created(int fd,int account_id,int char_id,struct party *p) { WFIFOHEAD(fd, 39); - WFIFOW(fd,0) = 0x3820; - WFIFOL(fd,2) = account_id; - WFIFOL(fd,6) = char_id; - if (p != NULL) { - WFIFOB(fd,10) = 0; - WFIFOL(fd,11) = p->party_id; - memcpy(WFIFOP(fd,15), p->name, NAME_LENGTH); - ShowInfo("Created party (%d - %s)\n", p->party_id, p->name); - } else { - WFIFOB(fd,10) = 1; - WFIFOL(fd,11) = 0; - memset(WFIFOP(fd,15), 0, NAME_LENGTH); + WFIFOW(fd,0)=0x3820; + WFIFOL(fd,2)=account_id; + WFIFOL(fd,6)=char_id; + if(p!=NULL){ + WFIFOB(fd,10)=0; + WFIFOL(fd,11)=p->party_id; + memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH); + ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name); + }else{ + WFIFOB(fd,10)=1; + WFIFOL(fd,11)=0; + memset(WFIFOP(fd,15),0,NAME_LENGTH); } WFIFOSET(fd,39); + return 0; } -// パ?ティ情報見つからず +// パーティ情報見つからず static void mapif_party_noinfo(int fd, int party_id, int char_id) { WFIFOHEAD(fd, 12); @@ -319,8 +359,7 @@ static void mapif_party_noinfo(int fd, int party_id, int char_id) WFIFOSET(fd,12); ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id); } - -// パ?ティ情報まとめ送り +// パーティ情報まとめ送り static void mapif_party_info(int fd, struct party* p, int char_id) { unsigned char buf[8 + sizeof(struct party)]; @@ -328,13 +367,13 @@ static void mapif_party_info(int fd, struct party* p, int char_id) 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)); + + if(fd<0) + mapif_sendall(buf,WBUFW(buf,2)); else - mapif_send(fd, buf, WBUFW(buf,2)); + mapif_send(fd,buf,WBUFW(buf,2)); } - -// パ?ティメンバ追加可否 +// パーティメンバ追加可否 int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag) { WFIFOHEAD(fd, 15); WFIFOW(fd,0) = 0x3822; @@ -347,24 +386,24 @@ int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, i return 0; } -// パ?ティ設定?更通知 -int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag) { - unsigned char buf[15]; - - WBUFW(buf,0) = 0x3823; - WBUFL(buf,2) = p->party_id; - WBUFL(buf,6) = account_id; - WBUFW(buf,10) = p->exp; - WBUFW(buf,12) = p->item; - WBUFB(buf,14) = flag; - if (flag == 0) - mapif_sendall(buf, 15); +// パーティ設定変更通知 +int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag) +{ + unsigned char buf[16]; + WBUFW(buf,0)=0x3823; + WBUFL(buf,2)=p->party_id; + WBUFL(buf,6)=account_id; + WBUFW(buf,10)=p->exp; + WBUFW(buf,12)=p->item; + WBUFB(buf,14)=flag; + if(flag==0) + mapif_sendall(buf,15); else - mapif_send(fd, buf, 15); + mapif_send(fd,buf,15); return 0; } -// パ?ティ?退通知 +// パーティ脱退通知 int mapif_party_withdraw(int party_id,int account_id, int char_id) { unsigned char buf[16]; @@ -376,8 +415,9 @@ int mapif_party_withdraw(int party_id,int account_id, int char_id) { return 0; } -// パ?ティマップ更新通知 -int mapif_party_membermoved(struct party *p, int idx) { +// パーティマップ更新通知 +int mapif_party_membermoved(struct party *p,int idx) +{ unsigned char buf[20]; WBUFW(buf,0) = 0x3825; @@ -391,29 +431,27 @@ int mapif_party_membermoved(struct party *p, int idx) { return 0; } -// パ?ティ解散通知 -int mapif_party_broken(int party_id, int flag) { - unsigned char buf[7]; - WBUFW(buf,0) = 0x3826; - WBUFL(buf,2) = party_id; - WBUFB(buf,6) = flag; - mapif_sendall(buf, 7); - ShowInfo("Party broken (%d)\n", party_id); - +// パーティ解散通知 +int mapif_party_broken(int party_id,int flag) +{ + unsigned char buf[16]; + WBUFW(buf,0)=0x3826; + WBUFL(buf,2)=party_id; + WBUFB(buf,6)=flag; + mapif_sendall(buf,7); + //printf("int_party: broken %d\n",party_id); return 0; } - -// パ?ティ??言 -int mapif_party_message(int party_id, int account_id, char *mes, int len, int sfd) { - unsigned char buf[2048]; - - WBUFW(buf,0) = 0x3827; - WBUFW(buf,2) = len + 12; - WBUFL(buf,4) = party_id; - WBUFL(buf,8) = account_id; - memcpy(WBUFP(buf,12), mes, len); - mapif_sendallwos(sfd, buf,len + 12); - +// パーティ内発言 +int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd) +{ + unsigned char buf[512]; + WBUFW(buf,0)=0x3827; + WBUFW(buf,2)=len+12; + WBUFL(buf,4)=party_id; + WBUFL(buf,8)=account_id; + memcpy(WBUFP(buf,12),mes,len); + mapif_sendallwos(sfd, buf,len+12); return 0; } @@ -421,83 +459,72 @@ int mapif_party_message(int party_id, int account_id, char *mes, int len, int sf // map serverからの通信 -// パ?ティ +// Create Party int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader) { struct party_data *p; int i; - - //FIXME: this should be removed once the savefiles can handle all symbols - for(i = 0; i < NAME_LENGTH && name[i]; i++) { - if (!(name[i] & 0xe0) || name[i] == 0x7f) { - ShowInfo("int_party: illegal party name [%s]\n", name); - mapif_party_created(fd, leader->account_id, leader->char_id, NULL); - return 0; - } - } - - if ((p = search_partyname(name)) != NULL) { - ShowInfo("int_party: same name party exists [%s]\n", name); - mapif_party_created(fd, leader->account_id, leader->char_id, NULL); + if( (p=search_partyname(name))!=NULL){ + mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } - // Check Authorised letters/symbols in the name of the character if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (i = 0; i < NAME_LENGTH && name[i]; i++) if (strchr(char_name_letters, name[i]) == NULL) { - mapif_party_created(fd, leader->account_id, leader->char_id, NULL); + mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden for (i = 0; i < NAME_LENGTH && name[i]; i++) if (strchr(char_name_letters, name[i]) != NULL) { - mapif_party_created(fd, leader->account_id, leader->char_id, NULL); + mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } } - p = (struct party_data *) aCalloc(sizeof(struct party_data), 1); - if (p == NULL) { - ShowFatalError("int_party: out of memory !\n"); - mapif_party_created(fd,leader->account_id,leader->char_id,NULL); - return 0; - } - p->party.party_id = party_newid++; - memcpy(p->party.name, name, NAME_LENGTH); - p->party.exp = 0; + p = (struct party_data*)aCalloc(1, sizeof(struct party_data)); + + memcpy(p->party.name,name,NAME_LENGTH); + p->party.exp=0; p->party.item=(item?1:0)|(item2?2:0); + memcpy(&p->party.member[0], leader, sizeof(struct party_member)); - p->party.member[0].leader = 1; - int_party_calc_state(p); - idb_put(party_db, p->party.party_id, p); + p->party.member[0].leader=1; + p->party.member[0].online=1; - mapif_party_info(fd, &p->party, 0); - mapif_party_created(fd, leader->account_id, leader->char_id, &p->party); + p->party.party_id=-1;//New party. + if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) { + //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); + } else { //Failed to create party. + aFree(p); + mapif_party_created(fd,leader->account_id,leader->char_id,NULL); + } return 0; } - -// パ?ティ情報要求 +// パーティ情報要求 static void mapif_parse_PartyInfo(int fd, int party_id, int char_id) { struct party_data *p; + p = inter_party_fromsql(party_id); - p = (struct party_data*)idb_get(party_db, party_id); - if (p != NULL) + if (p) mapif_party_info(fd, &p->party, char_id); - else { + else mapif_party_noinfo(fd, party_id, char_id); - } } - -// パーティ追加要求 +// パーティ追加要求 int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member) { struct party_data *p; int i; - p = (struct party_data*)idb_get(party_db, party_id); + p = inter_party_fromsql(party_id); if( p == NULL || p->size == MAX_PARTY ) { mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1); return 0; @@ -514,7 +541,7 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member p->party.member[i].leader = 0; if (p->party.member[i].online) p->party.count++; p->size++; - if (p->size == 3) //Check family state. + if (p->size == 2 || p->size == 3) // Check family state. And also accept either of their Parents. [RoM] int_party_calc_state(p); else //Check even share range. if (member->lv < p->min_lv || member->lv > p->max_lv || p->family) { @@ -524,67 +551,89 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member mapif_party_info(-1, &p->party, 0); mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0); + inter_party_tosql(&p->party, PS_ADDMEMBER, i); return 0; } -// パ?ティ?設定?更要求 -int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp, int item) +// パーティー設定変更要求 +int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item) { struct party_data *p; int flag = 0; + p = inter_party_fromsql(party_id); - p = (struct party_data*)idb_get(party_db, party_id); - if (p == NULL) + if(!p) return 0; - p->party.exp = exp; - if (exp>0 && !party_check_exp_share(p)) { - flag |= 0x01; - p->party.exp = 0; + p->party.exp=exp; + if( exp && !party_check_exp_share(p) ){ + flag|=0x01; + p->party.exp=0; } - p->party.item = item&0x3; - mapif_party_optionchanged(fd, &p->party, account_id, flag); + p->party.item = item&0x3; //Filter out invalid values. + mapif_party_optionchanged(fd,&p->party,account_id,flag); + inter_party_tosql(&p->party, PS_BASIC, 0); return 0; } - -// パ?ティ?退要求 +// パーティ脱退要求 int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) { struct party_data *p; - int i,lv; + int i,j=-1; - p = (struct party_data*)idb_get(party_db, party_id); - if (!p) return 0; + p = inter_party_fromsql(party_id); + if( p == NULL ) + {// Party does not exists? + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + Sql_ShowDebug(sql_handle); + return 0; + } - for(i = 0; i < MAX_PARTY; i++) { + for (i = 0; i < MAX_PARTY; i++) { if(p->party.member[i].account_id == account_id && - p->party.member[i].char_id == char_id) + p->party.member[i].char_id == char_id) { + break; + } + } + if (i >= MAX_PARTY) + return 0; //Member not found? + + mapif_party_withdraw(party_id, account_id, char_id); + + if (p->party.member[i].leader){ + p->party.member[i].account_id = 0; + for (j = 0; j < MAX_PARTY; j++) { + if (!p->party.member[j].account_id) + continue; + mapif_party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id); + p->party.member[j].account_id = 0; + } + //Party gets deleted on the check_empty call below. + } else { + inter_party_tosql(&p->party,PS_DELMEMBER,i); + j = p->party.member[i].lv; + if(p->party.member[i].online) p->party.count--; + memset(&p->party.member[i], 0, sizeof(struct party_member)); + p->size--; + if (j == p->min_lv || j == p->max_lv || p->family) { - mapif_party_withdraw(party_id, account_id, char_id); - lv = p->party.member[i].lv; - if(p->party.member[i].online) p->party.count--; - memset(&p->party.member[i], 0, sizeof(struct party_member)); - p->size--; - if (lv == p->min_lv || lv == p->max_lv || p->family) - { - if(p->family) p->family = 0; //Family state broken. - int_party_check_lv(p); - } - if (party_check_empty(&p->party) == 0) - mapif_party_info(-1, &p->party, 0); - return 0; + if(p->family) p->family = 0; //Family state broken. + int_party_check_lv(p); } } + + if (party_check_empty(p) == 0) + mapif_party_info(-1, &p->party, 0); return 0; } - +// When member goes to other map or levels up. int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv) { struct party_data *p; int i; - p = (struct party_data*)idb_get(party_db, party_id); + p = inter_party_fromsql(party_id); if (p == NULL) return 0; @@ -615,6 +664,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id //Send online/offline update. mapif_party_membermoved(&p->party, i); } + if (p->party.member[i].lv != lv) { if(p->party.member[i].lv == p->min_lv || p->party.member[i].lv == p->max_lv) @@ -626,6 +676,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id //There is no need to send level update to map servers //since they do nothing with it. } + if (p->party.member[i].map != map) { p->party.member[i].map = map; mapif_party_membermoved(&p->party, i); @@ -633,19 +684,23 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id return 0; } -// パ?ティ解散要求 -int mapif_parse_BreakParty(int fd, int party_id) { +// パーティ解散要求 +int mapif_parse_BreakParty(int fd,int party_id) +{ + struct party_data *p; - idb_remove(party_db, party_id); - mapif_party_broken(fd, party_id); + p = inter_party_fromsql(party_id); + if(!p) + return 0; + inter_party_tosql(&p->party,PS_BREAK,0); + mapif_party_broken(fd,party_id); return 0; } - -// パ?ティメッセ?ジ送信 -int mapif_parse_PartyMessage(int fd, int party_id, int account_id, char *mes, int len) +// パーティメッセージ送信 +int mapif_parse_PartyMessage(int fd,int party_id,int account_id,char *mes,int len) { - return mapif_party_message(party_id, account_id, mes, len, fd); + return mapif_party_message(party_id,account_id,mes,len, fd); } int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id) @@ -653,8 +708,9 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id struct party_data *p; int i; - p = (struct party_data*)idb_get(party_db, party_id); - if (p == NULL) + p = inter_party_fromsql(party_id); + + if(!p) return 0; for (i = 0; i < MAX_PARTY; i++) @@ -663,17 +719,21 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id p->party.member[i].leader = 0; if(p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id) + { p->party.member[i].leader = 1; + inter_party_tosql(&p->party,PS_LEADER, i); + } } return 1; } // map server からの通信 -// ?1パケットのみ解析すること -// ?パケット長デ?タはinter.cにセットしておくこと -// ?パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない -// ?エラ?なら0(false)、そうでないなら1(true)をかえさなければならない -int inter_party_parse_frommap(int fd) { +// ・1パケットのみ解析すること +// ・パケット長データはinter.cにセットしておくこと +// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない +// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない +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; @@ -688,12 +748,105 @@ int inter_party_parse_frommap(int fd) { default: return 0; } + return 1; +} + +// サーバーから脱退要求(キャラ削除用) +int inter_party_leave(int party_id,int account_id, int char_id) +{ + return mapif_parse_PartyLeave(-1,party_id,account_id, char_id); +} + +int inter_party_CharOnline(int char_id, int party_id) +{ + struct party_data* p; + int i; + + if( party_id == -1 ) + {// Get party_id from the database + char* data; + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); + return 0; + } + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + return 0; //Eh? No party? + + Sql_GetData(sql_handle, 0, &data, NULL); + party_id = atoi(data); + Sql_FreeResult(sql_handle); + } + if (party_id == 0) + return 0; //No party... + + p = inter_party_fromsql(party_id); + if(!p) { + ShowError("Character %d's party %d not found!\n", char_id, party_id); + return 0; + } + + //Set member online + for(i=0; i<MAX_PARTY; i++) { + if (p->party.member[i].char_id == char_id) { + if (!p->party.member[i].online) { + p->party.member[i].online = 1; + p->party.count++; + if (p->party.member[i].lv < p->min_lv || + p->party.member[i].lv > p->max_lv) + int_party_check_lv(p); + } + break; + } + } return 1; } -// サ?バ?から?退要求(キャラ削除用) -int inter_party_leave(int party_id, int account_id, int char_id) { - return mapif_parse_PartyLeave(-1, party_id, account_id, char_id); +int inter_party_CharOffline(int char_id, int party_id) { + struct party_data *p=NULL; + int i; + + if( party_id == -1 ) + {// Get guild_id from the database + char* data; + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); + return 0; + } + + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + return 0; //Eh? No party? + + Sql_GetData(sql_handle, 0, &data, NULL); + party_id = atoi(data); + Sql_FreeResult(sql_handle); + } + if (party_id == 0) + return 0; //No party... + + //Character has a party, set character offline and check if they were the only member online + if ((p = inter_party_fromsql(party_id)) == NULL) + return 0; + + //Set member offline + for(i=0; i< MAX_PARTY; i++) { + if(p->party.member[i].char_id == char_id) + { + p->party.member[i].online = 0; + p->party.count--; + if(p->party.member[i].lv == p->min_lv || + p->party.member[i].lv == p->max_lv) + int_party_check_lv(p); + break; + } + } + + if(!p->party.count) + //Parties don't have any data that needs be saved at this point... so just remove it from memory. + idb_remove(party_db_, party_id); + return 1; } -#endif //TXT_SQL_CONVERT |