From 36a95ec61ea84943977a663e74729354e0f0e373 Mon Sep 17 00:00:00 2001 From: ultramage Date: Fri, 31 Aug 2007 17:08:27 +0000 Subject: * Documented/cleaned up chatroom code and packetry * Added some comments to clif_changechatowner() - totally broken, see the code + topic:163829 * Implemented the chatroom display packet properly - now has 4 types: public, private, npc and non-clickable npc chatroom * Implemented the chatroom leave packet properly - now utilizes the 'kicked' flag when the user was forced to leave - TODO: banlist support to prevent re-entry, see jAthena code git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11100 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/chat.c | 75 +++++++++++++++------------- src/map/chat.h | 2 +- src/map/clif.c | 153 ++++++++++++++++++++++++++++++++------------------------- src/map/clif.h | 6 +-- src/map/map.h | 6 +-- src/map/unit.c | 2 +- 6 files changed, 135 insertions(+), 109 deletions(-) (limited to 'src') diff --git a/src/map/chat.c b/src/map/chat.c index 1f8166871..0a2b18d37 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -32,7 +32,7 @@ static struct chat_data* chat_createchat(struct block_list* bl, const char* titl safestrncpy(cd->pass, pass, sizeof(cd->pass)); cd->pub = pub; cd->users = 0; - cd->limit = limit; + cd->limit = min(limit, ARRAYSIZE(cd->usersd)); cd->trigger = trigger; memset(cd->usersd, 0, sizeof(cd->usersd)); cd->owner = bl; @@ -45,7 +45,8 @@ static struct chat_data* chat_createchat(struct block_list* bl, const char* titl cd->bl.next = cd->bl.prev = NULL; cd->bl.id = map_addobject(&cd->bl); - if( cd->bl.id == 0 ) { + if( cd->bl.id == 0 ) + { aFree(cd); cd = NULL; } @@ -61,23 +62,27 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char struct chat_data* cd; nullpo_retr(0, sd); - if (sd->chatID) + if( sd->chatID ) return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] - if (map[sd->bl.m].flag.nochat) { - clif_displaymessage (sd->fd, msg_txt(281)); + if( map[sd->bl.m].flag.nochat ) + { + clif_displaymessage(sd->fd, msg_txt(281)); return 0; //Can't create chatrooms on this map. } + pc_stop_walking(sd,1); cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, ""); - if (cd) { + if( cd ) + { cd->users = 1; cd->usersd[0] = sd; pc_setchatid(sd,cd->bl.id); clif_createchat(sd,0); clif_dispchat(cd,0); - } else + } + else clif_createchat(sd,1); return 0; @@ -93,11 +98,14 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) nullpo_retr(0, sd); cd = (struct chat_data*)map_id2bl(chatid); - if (cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->users >= cd->limit) { + if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->chatID || cd->users >= cd->limit ) + { clif_joinchatfail(sd,0); return 0; } - if (!cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !(battle_config.gm_join_chat && pc_isGM(sd) >= battle_config.gm_join_chat)) { + + if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !(battle_config.gm_join_chat && pc_isGM(sd) >= battle_config.gm_join_chat) ) + { clif_joinchatfail(sd,1); return 0; } @@ -121,7 +129,7 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) /*========================================== * leave a chatroom *------------------------------------------*/ -int chat_leavechat(struct map_session_data* sd) +int chat_leavechat(struct map_session_data* sd, bool kicked) { struct chat_data* cd; int i; @@ -138,23 +146,23 @@ int chat_leavechat(struct map_session_data* sd) ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd ); if ( i == cd->users ) - {// Not found in the chatroom? + { // Not found in the chatroom? pc_setchatid(sd, 0); return -1; } leavechar = i; - clif_leavechat(cd, sd); + clif_leavechat(cd, sd, kicked); for( i = leavechar; i < cd->users; i++ ) - cd->usersd[i] = cd->usersd[i + 1]; + cd->usersd[i] = cd->usersd[i+1]; pc_setchatid(sd, 0); cd->users--; if( cd->users == 0 && cd->owner->type == BL_PC ) - {// Delete empty chatroom + { // Delete empty chatroom clif_clearchat(cd, 0); map_delobject(cd->bl.id); return 1; @@ -187,29 +195,28 @@ int chat_changechatowner(struct map_session_data* sd, const char* nextownername) { struct chat_data* cd; struct map_session_data* tmpsd; - int i, nextowner; + int i; nullpo_retr(1, sd); cd = (struct chat_data*)map_id2bl(sd->chatID); - if (cd == NULL || (struct block_list*) sd != cd->owner) + if( cd == NULL || (struct block_list*) sd != cd->owner ) return 1; ARR_FIND( 1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0 ); - if (i == cd->users) + if( i == cd->users ) return -1; // name not found // erase temporarily clif_clearchat(cd,0); // set new owner - nextowner = i; - cd->owner = (struct block_list*) cd->usersd[nextowner]; - clif_changechatowner(cd,cd->usersd[nextowner]); + cd->owner = (struct block_list*) cd->usersd[i]; + clif_changechatowner(cd,cd->usersd[i]); - // change the owner's position (placing him to 0) - tmpsd = cd->usersd[nextowner]; - cd->usersd[nextowner] = cd->usersd[0]; + // swap the old and new owners' positions + tmpsd = cd->usersd[i]; + cd->usersd[i] = cd->usersd[0]; cd->usersd[0] = tmpsd; // set the new chatroom position @@ -233,13 +240,13 @@ int chat_changechatstatus(struct map_session_data* sd, const char* title, const nullpo_retr(1, sd); - cd=(struct chat_data*)map_id2bl(sd->chatID); - if(cd==NULL || (struct block_list *)sd != cd->owner) + cd = (struct chat_data*)map_id2bl(sd->chatID); + if( cd==NULL || (struct block_list *)sd != cd->owner ) return 1; safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE); safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE); - cd->limit = limit; + cd->limit = min(limit, ARRAYSIZE(cd->usersd)); cd->pub = pub; clif_changechatstatus(cd); @@ -260,17 +267,17 @@ int chat_kickchat(struct map_session_data* sd, const char* kickusername) cd = (struct chat_data *)map_id2bl(sd->chatID); - if (!cd) + if( !cd ) return -1; ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 ); - if (i == cd->users) + if( i == cd->users ) return -1; - if (battle_config.gm_kick_chat && pc_isGM(cd->usersd[i]) >= battle_config.gm_kick_chat) + if( battle_config.gm_kick_chat && pc_isGM(cd->usersd[i]) >= battle_config.gm_kick_chat ) return 0; //gm kick protection [Valaris] - chat_leavechat(cd->usersd[i]); + chat_leavechat(cd->usersd[i],1); return 0; } @@ -281,7 +288,7 @@ int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool p nullpo_retr(0, nd); cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev); - if (cd) + if( cd ) { nd->chat_id = cd->bl.id; clif_dispchat(cd,0); @@ -296,7 +303,7 @@ int chat_deletenpcchat(struct npc_data* nd) struct chat_data *cd; nullpo_retr(0, nd); - nullpo_retr(0, cd=(struct chat_data*)map_id2bl(nd->chat_id)); + nullpo_retr(0, cd = (struct chat_data*)map_id2bl(nd->chat_id)); chat_npckickall(cd); clif_clearchat(cd, 0); @@ -338,13 +345,13 @@ int chat_disableevent(struct chat_data* cd) return 0; } -/// Kicks all the users for the chat room. +/// Kicks all the users from the chat room. int chat_npckickall(struct chat_data* cd) { nullpo_retr(0, cd); while( cd->users > 0 ) - chat_leavechat(cd->usersd[cd->users-1]); + chat_leavechat(cd->usersd[cd->users-1],0); return 0; } diff --git a/src/map/chat.h b/src/map/chat.h index aac356584..d7bfb3f50 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -10,7 +10,7 @@ struct chat_data; int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass); -int chat_leavechat(struct map_session_data* sd); +int chat_leavechat(struct map_session_data* sd, bool kicked); int chat_changechatowner(struct map_session_data* sd, const char* nextownername); int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); int chat_kickchat(struct map_session_data* sd, const char* kickusername); diff --git a/src/map/clif.c b/src/map/clif.c index 9a3e5e7d9..8af8de5d8 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -3156,43 +3156,50 @@ int clif_useitemack(struct map_session_data *sd,int index,int amount,int ok) } /*========================================== - * + * Inform client whether chatroom creation was successful or not + * R 00d6 .B *------------------------------------------*/ -int clif_createchat(struct map_session_data *sd,int fail) +void clif_createchat(struct map_session_data* sd, int fail) { int fd; - nullpo_retr(0, sd); + nullpo_retv(sd); - fd=sd->fd; + fd = sd->fd; WFIFOHEAD(fd,packet_len(0xd6)); - WFIFOW(fd,0)=0xd6; - WFIFOB(fd,2)=fail; + WFIFOW(fd,0) = 0xd6; + WFIFOB(fd,2) = fail; WFIFOSET(fd,packet_len(0xd6)); - - return 0; } /*========================================== - * + * Display a chat above the owner + * R 00d7 .w .l .l .w .w .B .?B *------------------------------------------*/ int clif_dispchat(struct chat_data* cd, int fd) { - unsigned char buf[128]; // 最大title(60バイト)+17 + unsigned char buf[128]; + uint8 type; - if(cd==NULL || cd->owner==NULL) + if( cd == NULL || cd->owner == NULL ) return 1; - WBUFW(buf,0)=0xd7; - WBUFW(buf,2)=strlen((const char*)cd->title)+17; - WBUFL(buf,4)=cd->owner->id; - WBUFL(buf,8)=cd->bl.id; - WBUFW(buf,12)=cd->limit; - WBUFW(buf,14)=cd->users; - WBUFB(buf,16)=cd->pub; - strcpy((char*)WBUFP(buf,17),(const char*)cd->title); - if(fd){ - WFIFOHEAD(fd, WBUFW(buf,2)); + // type - 0: private, 1: public, 2: npc, 3: non-clickable + type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0 + : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 + : 1; + + WBUFW(buf, 0) = 0xd7; + WBUFW(buf, 2) = 17 + strlen(cd->title); + WBUFL(buf, 4) = cd->owner->id; + WBUFL(buf, 8) = cd->bl.id; + WBUFW(buf,12) = cd->limit; + WBUFW(buf,14) = cd->users; + WBUFB(buf,16) = type; + strncpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + + if( fd ) { + WFIFOHEAD(fd,WBUFW(buf,2)); memcpy(WFIFOP(fd,0),buf,WBUFW(buf,2)); WFIFOSET(fd,WBUFW(buf,2)); } else { @@ -3203,24 +3210,25 @@ int clif_dispchat(struct chat_data* cd, int fd) } /*========================================== - * chatの状態変更成功 - * 外部の人用と命令コード(d7->df)が違うだけ + * Chatroom properties adjustment + * R 00df <len>.w <owner ID>.l <chat ID>.l <limit>.w <users>.w <pub>.B <title>.?B *------------------------------------------*/ -int clif_changechatstatus(struct chat_data *cd) +int clif_changechatstatus(struct chat_data* cd) { - unsigned char buf[128]; // 最大title(60バイト)+17 + unsigned char buf[128]; - if(cd==NULL || cd->usersd[0]==NULL) + if( cd == NULL || cd->usersd[0] == NULL ) return 1; - WBUFW(buf,0)=0xdf; - WBUFW(buf,2)=strlen((char*)cd->title)+17; - WBUFL(buf,4)=cd->usersd[0]->bl.id; - WBUFL(buf,8)=cd->bl.id; - WBUFW(buf,12)=cd->limit; - WBUFW(buf,14)=cd->users; - WBUFB(buf,16)=cd->pub; - strcpy((char*)WBUFP(buf,17),(const char*)cd->title); + WBUFW(buf, 0) = 0xdf; + WBUFW(buf, 2) = 17 + strlen(cd->title); + WBUFL(buf, 4) = cd->usersd[0]->bl.id; + WBUFL(buf, 8) = cd->bl.id; + WBUFW(buf,12) = cd->limit; + WBUFW(buf,14) = cd->users; + WBUFB(buf,16) = cd->pub; + strncpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + clif_send(buf,WBUFW(buf,2),&cd->usersd[0]->bl,CHAT); return 0; @@ -3235,9 +3243,9 @@ int clif_clearchat(struct chat_data *cd,int fd) nullpo_retr(0, cd); - WBUFW(buf,0)=0xd8; - WBUFL(buf,2)=cd->bl.id; - if(fd){ + WBUFW(buf,0) = 0xd8; + WBUFL(buf,2) = cd->bl.id; + if( fd ) { WFIFOHEAD(fd,packet_len(0xd8)); memcpy(WFIFOP(fd,0),buf,packet_len(0xd8)); WFIFOSET(fd,packet_len(0xd8)); @@ -3257,11 +3265,11 @@ int clif_joinchatfail(struct map_session_data *sd,int fail) nullpo_retr(0, sd); - fd=sd->fd; + fd = sd->fd; WFIFOHEAD(fd,packet_len(0xda)); - WFIFOW(fd,0)=0xda; - WFIFOB(fd,2)=fail; + WFIFOW(fd,0) = 0xda; + WFIFOB(fd,2) = fail; WFIFOSET(fd,packet_len(0xda)); return 0; @@ -3313,45 +3321,48 @@ int clif_addchat(struct chat_data* cd,struct map_session_data *sd) } /*========================================== - * + * Announce the new owner + * R 00e1 <index>.l <nick>.24B *------------------------------------------*/ -int clif_changechatowner(struct chat_data* cd, struct map_session_data* sd) +void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd) { unsigned char buf[64]; - nullpo_retr(0, sd); - nullpo_retr(0, cd); + nullpo_retv(sd); + nullpo_retv(cd); + + //FIXME: this announces a swap between positions 0 and 1 (probably not what we want) [ultramage] + //FIXME: aegis sends obviously incorrect packets; need to figure out what to send to display it correctly :X + //TODO: is it just owner swap, or can it do general-purpose reordering? WBUFW(buf, 0) = 0xe1; WBUFL(buf, 2) = 1; memcpy(WBUFP(buf,6),cd->usersd[0]->status.name,NAME_LENGTH); + WBUFW(buf,30) = 0xe1; WBUFL(buf,32) = 0; memcpy(WBUFP(buf,36),sd->status.name,NAME_LENGTH); clif_send(buf,packet_len(0xe1)*2,&sd->bl,CHAT); - - return 0; } /*========================================== - * + * Notify about user leaving the chatroom + * R 00dd <index>.w <nick>.24B <flag>.B *------------------------------------------*/ -int clif_leavechat(struct chat_data* cd,struct map_session_data *sd) +void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag) { unsigned char buf[32]; - nullpo_retr(0, sd); - nullpo_retr(0, cd); + nullpo_retv(sd); + nullpo_retv(cd); WBUFW(buf, 0) = 0xdd; WBUFW(buf, 2) = cd->users-1; memcpy(WBUFP(buf,4),sd->status.name,NAME_LENGTH); - WBUFB(buf,28) = 0; + WBUFB(buf,28) = flag; // 0: left, 1: was kicked clif_send(buf,packet_len(0xdd),&sd->bl,CHAT); - - return 0; } /*========================================== @@ -9215,13 +9226,14 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) } /*========================================== - * + * Chatroom creation request + * S 00d5 <len>.w <limit>.w <pub>.B <passwd>.8B <title>.?B *------------------------------------------*/ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) { int len = RFIFOW(fd,2)-15; int limit = RFIFOW(fd,4); - bool public = (bool)RFIFOB(fd,6); + bool pub = (RFIFOB(fd,6) != 0); const char* password = (char*)RFIFOP(fd,7); //not zero-terminated const char* title = (char*)RFIFOP(fd,15); // not zero-terminated char s_title[CHATROOM_TITLE_SIZE]; @@ -9237,26 +9249,31 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); safestrncpy(s_password, password, CHATROOM_PASS_SIZE); - chat_createpcchat(sd, s_title, s_password, limit, public); + chat_createpcchat(sd, s_title, s_password, limit, pub); } /*========================================== - * + * Chatroom join request + * S 00d9 <chat ID>.l <passwd>.8B *------------------------------------------*/ -void clif_parse_ChatAddMember(int fd,struct map_session_data *sd) +void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) { - chat_joinchat(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); + int chatid = RFIFOL(fd,2); + const char* password = (char*)RFIFOP(fd,6); // not zero-terminated + + chat_joinchat(sd,chatid,password); } /*========================================== + * Chatroom properties adjustment request * S 00de <len>.w <limit>.w <pub>.B <passwd>.8B <title>.?B *------------------------------------------*/ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) { int len = RFIFOW(fd,2)-15; int limit = RFIFOW(fd,4); - bool public = (bool)RFIFOB(fd,6); - const char* password = (char*)RFIFOP(fd,7); //not zero-terminated + bool pub = (RFIFOB(fd,6) != 0); + const char* password = (char*)RFIFOP(fd,7); // not zero-terminated const char* title = (char*)RFIFOP(fd,15); // not zero-terminated char s_title[CHATROOM_TITLE_SIZE]; @@ -9264,14 +9281,15 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); safestrncpy(s_password, password, CHATROOM_PASS_SIZE); - chat_changechatstatus(sd, s_title, s_password, limit, public); + chat_changechatstatus(sd, s_title, s_password, limit, pub); } /*========================================== - * + * S 00e0 ?.l <nick>.24B *------------------------------------------*/ -void clif_parse_ChangeChatOwner(int fd,struct map_session_data *sd) +void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) { + //TODO: the first argument seems to be the destination position (always 0) [ultramage] chat_changechatowner(sd,(char*)RFIFOP(fd,6)); } @@ -9284,11 +9302,12 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) } /*========================================== - * + * Request to leave the current chatroom + * S 00e3 *------------------------------------------*/ -void clif_parse_ChatLeave(int fd,struct map_session_data *sd) +void clif_parse_ChatLeave(int fd, struct map_session_data* sd) { - chat_leavechat(sd); + chat_leavechat(sd,0); } //Handles notifying asker and rejecter of what has just ocurred. diff --git a/src/map/clif.h b/src/map/clif.h index dd0fff340..54a643b85 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -138,14 +138,14 @@ int clif_changeoption(struct block_list*); // area int clif_changeoption2(struct block_list*); // area int clif_useitemack(struct map_session_data*,int,int,int); // self void clif_GlobalMessage(struct block_list* bl, const char* message); -int clif_createchat(struct map_session_data*,int); // self +void clif_createchat(struct map_session_data* sd, int fail); // self int clif_dispchat(struct chat_data*,int); // area or fd int clif_joinchatfail(struct map_session_data*,int); // self int clif_joinchatok(struct map_session_data*,struct chat_data*); // self int clif_addchat(struct chat_data*,struct map_session_data*); // chat -int clif_changechatowner(struct chat_data*,struct map_session_data*); // chat +void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd); // chat int clif_clearchat(struct chat_data*,int); // area or fd -int clif_leavechat(struct chat_data*,struct map_session_data*); // chat +void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag); // chat int clif_changechatstatus(struct chat_data*); // chat int clif_refresh(struct map_session_data*); // self diff --git a/src/map/map.h b/src/map/map.h index c7a6556c5..5a8c55315 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1140,9 +1140,9 @@ struct chat_data { char title[CHATROOM_TITLE_SIZE]; // room title char pass[CHATROOM_PASS_SIZE]; // password bool pub; // private/public flag - unsigned char users; // current users - unsigned char limit; // join limit - unsigned char trigger; // number of users needed to trigger event + uint8 users; // current user count + uint8 limit; // join limit + uint8 trigger; // number of users needed to trigger event struct map_session_data* usersd[20]; struct block_list* owner; char npc_event[50]; diff --git a/src/map/unit.c b/src/map/unit.c index ba3f9926a..05175a991 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1674,7 +1674,7 @@ int unit_remove_map(struct block_list *bl, int clrtype) //Leave/reject all invitations. if(sd->chatID) - chat_leavechat(sd); + chat_leavechat(sd,0); if(sd->trade_partner) trade_tradecancel(sd); if(sd->vender_id) -- cgit v1.2.3-70-g09d2