From 5066af1700e95b5db24f9998cf1ff052b45f5fa0 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 22 Jan 2015 18:10:46 +0100 Subject: Channels refactoring: join Signed-off-by: Haru --- src/map/atcommand.c | 57 +++++++++++------------------------ src/map/channel.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++----- src/map/channel.h | 6 +++- src/map/clif.c | 15 ++-------- src/map/guild.c | 18 +++-------- src/map/pc.h | 1 - 6 files changed, 107 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/map/atcommand.c b/src/map/atcommand.c index bf99d4c20..0f33a387c 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -8612,9 +8612,11 @@ ACMD(cart) { #undef MC_CART_MDFY } /* [Ind/Hercules] */ -ACMD(join) { +ACMD(join) +{ struct channel_data *chan = NULL; char name[HCS_NAME_LENGTH], pass[HCS_NAME_LENGTH]; + enum channel_operation_status ret = HCS_STATUS_OK; if (!message || !*message || sscanf(message, "%19s %19s", name, pass) < 1) { sprintf(atcmd_output, msg_txt(1399),command); // Unknown Channel (usage: %s <#channel_name>) @@ -8632,56 +8634,35 @@ ACMD(join) { struct guild *g = sd->guild; if( !g ) return false;/* unlikely, but we wont let it crash anyway. */ chan = g->channel; - } else if( !( chan = strdb_get(channel->db, name + 1) ) ) { - sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>) - clif->message(fd, atcmd_output); - return false; + } else { + chan = strdb_get(channel->db, name + 1); } - if( !chan ) { + if(!chan) { sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>) clif->message(fd, atcmd_output); return false; } - if( idb_exists(chan->users, sd->status.char_id) ) { + ret = channel->join(chan, sd, pass, false); + + if (ret == HCS_STATUS_ALREADY) { sprintf(atcmd_output, msg_txt(1436),name); // You're already in the '%s' channel clif->message(fd, atcmd_output); return false; } - if( chan->password[0] != '\0' && strcmp(chan->password,pass) != 0 ) { - if( pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { - sd->stealth = true; - } else { - sprintf(atcmd_output, msg_txt(1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> ) - clif->message(fd, atcmd_output); - return false; - } - } - if( chan->banned && idb_exists(chan->banned, sd->status.account_id) ) { - sprintf(atcmd_output, msg_txt(1438),name); // You cannot join the '%s' channel because you've been banned from it + if (ret == HCS_STATUS_NOPERM) { + sprintf(atcmd_output, msg_txt(1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> ) clif->message(fd, atcmd_output); return false; } - if (!(chan->options & HCS_OPT_ANNOUNCE_JOIN)) { - sprintf(atcmd_output, msg_txt(1403),name); // You're now in the '%s' channel + if (ret == HCS_STATUS_BANNED) { + sprintf(atcmd_output, msg_txt(1438),name); // You cannot join the '%s' channel because you've been banned from it clif->message(fd, atcmd_output); + return false; } - if( chan->type == HCS_TYPE_ALLY ) { - struct guild *g = sd->guild; - int i; - for (i = 0; i < MAX_GUILDALLIANCE; i++) { - struct guild *sg = NULL; - if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) { - if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) { - channel->join(sg->channel,sd); - } - } - } - } - channel->join(chan,sd); return true; } @@ -8750,6 +8731,7 @@ ACMD(channel) { if (strcmpi(subcmd,"create") == 0 && (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) { // sub1 = channel name; sub2 = password; sub3 = unused size_t len = strlen(sub1); + const char *pass = *sub2 ? sub2 : NULL; if (sub1[0] != '#') { clif->message(fd, msg_txt(1405));// Channel name must start with a '#' return false; @@ -8768,15 +8750,10 @@ ACMD(channel) { } chan = channel->create(HCS_TYPE_PRIVATE, sub1 + 1, 0); - channel->set_password(chan, sub2); + channel->set_password(chan, pass); chan->owner = sd->status.char_id; - if( !( chan->options & HCS_OPT_ANNOUNCE_JOIN ) ) { - sprintf(atcmd_output, msg_txt(1403),sub1); // You're now in the '%s' channel - clif->message(fd, atcmd_output); - } - - channel->join(chan,sd); + channel->join(chan, sd, pass, false); } else if (strcmpi(subcmd,"list") == 0) { // sub1 = list type; sub2 = unused; sub3 = unused if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) { diff --git a/src/map/channel.c b/src/map/channel.c index b0640eeff..49f5c9daa 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -196,17 +196,25 @@ void channel_send(struct channel_data *chan, struct map_session_data *sd, const } } -void channel_join(struct channel_data *chan, struct map_session_data *sd) +/** + * Joins a channel, without any permission checks. + * + * @param chan The channel to join + * @param sd The character + * @param stealth If true, hide join announcements. + */ +void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bool stealth) { + nullpo_retv(chan); + nullpo_retv(sd); + if (idb_put(chan->users, sd->status.char_id, sd)) return; RECREATE(sd->channels, struct channel_data *, ++sd->channel_count); sd->channels[ sd->channel_count - 1 ] = chan; - if (sd->stealth) { - sd->stealth = false; - } else if (chan->options & HCS_OPT_ANNOUNCE_JOIN) { + if (!stealth && (chan->options&HCS_OPT_ANNOUNCE_JOIN)) { char message[60]; sprintf(message, "#%s '%s' joined",chan->name,sd->status.name); clif->channel_msg(chan,sd,message); @@ -219,6 +227,69 @@ void channel_join(struct channel_data *chan, struct map_session_data *sd) } +/** + * Joins a channel. + * + * Ban and password checks are performed before joining the channel. + * If the channel is an HCS_TYPE_ALLY channel, alliance channels are automatically joined. + * + * @param chan The channel to join + * @param sd The character + * @param password The specified join password, if any + * @param silent If true, suppress the "You're now in the channel" greeting message + * @retval HCS_STATUS_OK if the operation succeeded + * @retval HCS_STATUS_ALREADY if the character is already in the channel + * @retval HCS_STATUS_NOPERM if the specified password doesn't match + * @retval HCS_STATUS_BANNED if the character is in the channel's ban list + * @retval HCS_STATUS_FAIL in case of generic error + */ +enum channel_operation_status channel_join(struct channel_data *chan, struct map_session_data *sd, const char *password, bool silent) +{ + bool stealth = false; + + nullpo_retr(HCS_STATUS_FAIL, chan); + nullpo_retr(HCS_STATUS_FAIL, sd); + + if (idb_exists(chan->users, sd->status.char_id)) { + return HCS_STATUS_ALREADY; + } + + if (chan->password[0] != '\0' && strcmp(chan->password, password) != 0) { + if (pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { + stealth = true; + } else { + return HCS_STATUS_NOPERM; + } + } + + if (chan->banned && idb_exists(chan->banned, sd->status.account_id)) { + return HCS_STATUS_BANNED; + } + + if (!silent && !(chan->options&HCS_OPT_ANNOUNCE_JOIN)) { + char output[CHAT_SIZE_MAX]; + sprintf(output, msg_txt(1403), chan->name); // You're now in the '%s' channel + clif->message(sd->fd, output); + } + + if (chan->type == HCS_TYPE_ALLY) { + struct guild *g = sd->guild; + int i; + for (i = 0; i < MAX_GUILDALLIANCE; i++) { + struct guild *sg = NULL; + if (g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id))) { + if (!(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) { + channel->join_sub(sg->channel, sd, stealth); + } + } + } + } + + channel->join_sub(chan, sd, stealth); + + return HCS_STATUS_OK; +} + void channel_map_join(struct map_session_data *sd) { if (sd->state.autotrade || sd->state.standalone) @@ -235,7 +306,7 @@ void channel_map_join(struct map_session_data *sd) return; } - channel->join(map->list[sd->bl.m].channel,sd); + channel->join_sub(map->list[sd->bl.m].channel,sd, false); if (!( map->list[sd->bl.m].channel->options & HCS_OPT_ANNOUNCE_JOIN )) { char mout[60]; @@ -414,7 +485,7 @@ void channel_guild_join(struct guild *g1,struct guild *g2) for(j = 0; j < g2->max_member; j++) { if( (sd = g2->member[j].sd) != NULL ) { if( !(g1->channel->banned && idb_exists(g1->channel->banned, sd->status.account_id))) - channel->join(chan,sd); + channel->join_sub(chan,sd, false); } } } @@ -423,7 +494,7 @@ void channel_guild_join(struct guild *g1,struct guild *g2) for(j = 0; j < g1->max_member; j++) { if( (sd = g1->member[j].sd) != NULL ) { if( !(g2->channel->banned && idb_exists(g2->channel->banned, sd->status.account_id))) - channel->join(chan,sd); + channel->join_sub(chan,sd, false); } } } @@ -712,6 +783,7 @@ void channel_defaults(void) channel->set_options = channel_set_options; channel->send = channel_send; + channel->join_sub = channel_join_sub; channel->join = channel_join; channel->leave = channel_leave; channel->delete = channel_delete; diff --git a/src/map/channel.h b/src/map/channel.h index 11ba968a9..8709a9f96 100644 --- a/src/map/channel.h +++ b/src/map/channel.h @@ -40,6 +40,7 @@ enum channel_operation_status { HCS_STATUS_FAIL, HCS_STATUS_ALREADY, HCS_STATUS_NOPERM, + HCS_STATUS_BANNED, }; /** @@ -85,6 +86,7 @@ struct channel_interface { int (*init) (bool minimal); void (*final) (void); + struct channel_data *(*search) (const char *name); struct channel_data *(*create) (enum channel_types type, const char *name, unsigned char color); void (*set_password) (struct channel_data *chan, const char *password); enum channel_operation_status (*ban) (struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd); @@ -92,7 +94,9 @@ struct channel_interface { void (*set_options) (struct channel_data *chan, unsigned int options); void (*send) (struct channel_data *chan, struct map_session_data *sd, const char *msg); - void (*join) (struct channel_data *chan, struct map_session_data *sd); + void (*join_sub) (struct channel_data *chan, struct map_session_data *sd, bool stealth); + enum channel_operation_status (*join) (struct channel_data *chan, struct map_session_data *sd, const char *password, bool silent); + void (*leave) (struct channel_data *chan, struct map_session_data *sd); void (*delete) (struct channel_data *chan); void (*map_join) (struct map_session_data *sd); diff --git a/src/map/clif.c b/src/map/clif.c index 10ab7121a..c66176d45 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -10062,20 +10062,9 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if( sd->channels[k] == chan ) break; } - if( k < sd->channel_count ) { + if (k < sd->channel_count) { channel->send(chan,sd,message); - } else if( chan->password[0] == '\0' && !(chan->banned && idb_exists(chan->banned, sd->status.account_id)) ) { - if( chan->type == HCS_TYPE_ALLY ) { - struct guild *g = sd->guild; - for (k = 0; k < MAX_GUILDALLIANCE; k++) { - struct guild *sg = NULL; - if( g->alliance[k].opposition == 0 && g->alliance[k].guild_id && (sg = guild->search(g->alliance[k].guild_id) ) ) { - if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) - channel->join(sg->channel,sd); - } - } - } - channel->join(chan,sd); + } else if (channel->join(chan, sd, NULL, true) == HCS_STATUS_OK) { channel->send(chan,sd,message); } else { clif->message(fd, msg_txt(1402)); diff --git a/src/map/guild.c b/src/map/guild.c index 3e71e99dc..a33efb831 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -489,13 +489,13 @@ int guild_recv_info(struct guild *sg) { if (sd->status.guild_id == sg->guild_id) { // Guild member - channel->join(chan,sd); + channel->join_sub(chan,sd,false); sd->guild = g; for (i = 0; i < MAX_GUILDALLIANCE; i++) { // Join channels from allied guilds if (tg[i] && !(tg[i]->channel->banned && idb_exists(tg[i]->channel->banned, sd->status.account_id))) - channel->join(tg[i]->channel, sd); + channel->join_sub(tg[i]->channel, sd, false); } continue; } @@ -504,7 +504,7 @@ int guild_recv_info(struct guild *sg) { if (tg[i] && sd->status.guild_id == tg[i]->guild_id) { // Shortcut to skip the alliance checks again // Alliance member if( !(chan->banned && idb_exists(chan->banned, sd->status.account_id))) - channel->join(chan, sd); + channel->join_sub(chan, sd, false); } } } @@ -741,17 +741,7 @@ void guild_member_joined(struct map_session_data *sd) sd->guild = g; if (channel->config->ally && channel->config->ally_autojoin) { - struct channel_data *chan = g->channel; - - if( !(chan->banned && idb_exists(chan->banned, sd->status.account_id) ) ) - channel->join(chan,sd); - for (i = 0; i < MAX_GUILDALLIANCE; i++) { - struct guild* sg = NULL; - if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) { - if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) - channel->join(sg->channel,sd); - } - } + channel->join(g->channel, sd, NULL, true); } } diff --git a/src/map/pc.h b/src/map/pc.h index 167aa6010..f6b6329b4 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -494,7 +494,6 @@ struct map_session_data { struct channel_data **channels; unsigned char channel_count; struct channel_data *gcbind; - bool stealth; unsigned char fontcolor; unsigned int fontcolor_tid; int64 hchsysch_tick; -- cgit v1.2.3-60-g2f50