* 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://svn.code.sf.net/p/rathena/svn/trunk@11100 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-08-31 17:08:27 +00:00
parent 2f4c475e13
commit 1481fc1524
7 changed files with 144 additions and 109 deletions

View File

@ -3,6 +3,15 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/08/31
* 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
* Documented/cleaned up chatroom code and packetry [ultramage]
2007/08/30
* Updated sql files [Playtester]
2007/08/29

View File

@ -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;
}

View File

@ -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);

View File

@ -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 <fail>.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 <len>.w <owner ID>.l <chat ID>.l <limit>.w <users>.w <type>.B <title>.?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.

View File

@ -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

View File

@ -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];

View File

@ -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)