From d355711bbb75c08d0326f737432998a95eebaffb Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 22 Jan 2015 19:37:07 +0100 Subject: Channels refactoring: quit, leave, delete Signed-off-by: Haru --- src/map/channel.c | 158 ++++++++++++++++++++++++++++-------------------------- src/map/channel.h | 11 ++-- src/map/map.c | 4 -- src/map/pc.c | 2 +- 4 files changed, 90 insertions(+), 85 deletions(-) diff --git a/src/map/channel.c b/src/map/channel.c index aa7b10ba3..88e0c4689 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -80,10 +80,13 @@ struct channel_data *channel_search(const char *name, struct map_session_data *s struct channel_data *channel_create(enum channel_types type, const char *name, unsigned char color) { struct channel_data *chan; + + if (!name) + return NULL; + CREATE(chan, struct channel_data, 1); chan->users = idb_alloc(DB_OPT_BASE); - if (name) - safestrncpy(chan->name, name, HCS_NAME_LENGTH); + safestrncpy(chan->name, name, HCS_NAME_LENGTH); chan->color = color; chan->options = HCS_OPT_BASE; @@ -97,50 +100,37 @@ struct channel_data *channel_create(enum channel_types type, const char *name, u return chan; } +/** + * Deletes a chat channel. + * + * @param chan The channel to delete + */ void channel_delete(struct channel_data *chan) { + nullpo_retv(chan); + if (db_size(chan->users) && !channel->config->closing) { DBIterator *iter; struct map_session_data *sd; - unsigned char i; iter = db_iterator(chan->users); - for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { - for( i = 0; i < sd->channel_count; i++ ) { - if( sd->channels[i] == chan ) { - sd->channels[i] = NULL; - break; - } - } - if( i < sd->channel_count ) { - unsigned char cursor = 0; - for( i = 0; i < sd->channel_count; i++ ) { - if( sd->channels[i] == NULL ) - continue; - if( cursor != i ) { - sd->channels[cursor] = sd->channels[i]; - } - cursor++; - } - if ( !(sd->channel_count = cursor) ) { - aFree(sd->channels); - sd->channels = NULL; - } - } + for (sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) { + channel->leave_sub(chan, sd); } dbi_destroy(iter); } - if( chan->banned ) { + if (chan->banned) { db_destroy(chan->banned); chan->banned = NULL; } db_destroy(chan->users); - if( chan->m ) { + if (chan->m) { map->list[chan->m].channel = NULL; aFree(chan); - } else if ( chan->type == HCS_TYPE_ALLY ) + } else if (chan->type == HCS_TYPE_ALLY) { aFree(chan); - else if (!channel->config->closing) + } else if (!channel->config->closing) { strdb_remove(channel->db, chan->name); + } } /** @@ -294,7 +284,7 @@ void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bo return; RECREATE(sd->channels, struct channel_data *, ++sd->channel_count); - sd->channels[ sd->channel_count - 1 ] = chan; + sd->channels[sd->channel_count - 1] = chan; if (!stealth && (chan->options&HCS_OPT_ANNOUNCE_JOIN)) { char message[60]; @@ -351,7 +341,7 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map if (!silent && !(chan->options&HCS_OPT_ANNOUNCE_JOIN)) { char output[CHAT_SIZE_MAX]; if (chan->type == HCS_TYPE_MAP) { - sprintf(output, msg_txt(1435), chan->name, map->list[sd->bl.m].name); // You're now in the '#%s' channel for '%s' + sprintf(output, msg_txt(1435), chan->name, map->list[chan->m].name); // You're now in the '#%s' channel for '%s' } else { sprintf(output, msg_txt(1403), chan->name); // You're now in the '%s' channel } @@ -376,75 +366,88 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map return HCS_STATUS_OK; } -void channel_leave(struct channel_data *chan, struct map_session_data *sd) +/** + * Removes a channel from a character's join lists. + * + * @param chan The channel to leave + * @param sd The character + */ +void channel_leave_sub(struct channel_data *chan, struct map_session_data *sd) { unsigned char i; - if ( !idb_remove(chan->users,sd->status.char_id) ) - return; - - if( chan == sd->gcbind ) - sd->gcbind = NULL; - - if( !db_size(chan->users) && chan->type == HCS_TYPE_PRIVATE ) { - channel->delete(chan); - } else if( !channel->config->closing && (chan->options & HCS_OPT_ANNOUNCE_JOIN) ) { - char message[60]; - sprintf(message, "#%s '%s' left",chan->name,sd->status.name); - clif->channel_msg(chan,sd,message); - } - - for( i = 0; i < sd->channel_count; i++ ) { - if( sd->channels[i] == chan ) { + nullpo_retv(chan); + nullpo_retv(sd); + for (i = 0; i < sd->channel_count; i++) { + if (sd->channels[i] == chan) { sd->channels[i] = NULL; break; } } - - if( i < sd->channel_count ) { + if (i < sd->channel_count) { unsigned char cursor = 0; - for( i = 0; i < sd->channel_count; i++ ) { - if( sd->channels[i] == NULL ) + for (i = 0; i < sd->channel_count; i++) { + if (sd->channels[i] == NULL) continue; - if( cursor != i ) { + if (cursor != i) { sd->channels[cursor] = sd->channels[i]; } cursor++; } - if ( !(sd->channel_count = cursor) ) { + if (!(sd->channel_count = cursor)) { aFree(sd->channels); sd->channels = NULL; } } - } - -void channel_quit(struct map_session_data *sd) +/** + * Leaves a channel. + * + * @param chan The channel to leave + * @param sd The character + */ +void channel_leave(struct channel_data *chan, struct map_session_data *sd) { - unsigned char i; + nullpo_retv(chan); + nullpo_retv(sd); - for (i = 0; i < sd->channel_count; i++) { - struct channel_data *chan = sd->channels[i]; - if (chan != NULL) { - idb_remove(chan->users,sd->status.char_id); + if (!idb_remove(chan->users,sd->status.char_id)) + return; - if( chan == sd->gcbind ) - sd->gcbind = NULL; + if (chan == sd->gcbind) + sd->gcbind = NULL; - if (!db_size(chan->users) && chan->type == HCS_TYPE_PRIVATE) { - channel->delete(chan); - } else if (!channel->config->closing && (chan->options & HCS_OPT_ANNOUNCE_JOIN)) { - char message[60]; - sprintf(message, "#%s '%s' left",chan->name,sd->status.name); - clif->channel_msg(chan,sd,message); - } + if (!db_size(chan->users) && chan->type == HCS_TYPE_PRIVATE) { + channel->delete(chan); + } else if (!channel->config->closing && (chan->options & HCS_OPT_ANNOUNCE_JOIN)) { + char message[60]; + sprintf(message, "#%s '%s' left",chan->name,sd->status.name); + clif->channel_msg(chan,sd,message); + } + + channel->leave_sub(chan, sd); +} + +/** + * Quits the channel system. + * + * Leaves all joined channels. + * + * @param sd The target character + */ +void channel_quit(struct map_session_data *sd) +{ + while (sd->channel_count > 0) { + // Loop downward to avoid unnecessary array compactions by channel_leave + struct channel_data *chan = sd->channels[sd->channel_count-1]; + if (chan == NULL) { + sd->channel_count--; + continue; } - } - sd->channel_count = 0; - aFree(sd->channels); - sd->channels = NULL; + channel->leave(chan, sd); + } } /** @@ -807,9 +810,11 @@ void channel_defaults(void) { channel = &channel_s; + channel->db = NULL; + channel->config = &channel_config; + channel->init = do_init_channel; channel->final = do_final_channel; - channel->config = &channel_config; channel->search = channel_search; channel->create = channel_create; @@ -824,6 +829,7 @@ void channel_defaults(void) channel->join_sub = channel_join_sub; channel->join = channel_join; channel->leave = channel_leave; + channel->leave_sub = channel_leave_sub; channel->quit = channel_quit; channel->map_join = channel_map_join; diff --git a/src/map/channel.h b/src/map/channel.h index 39127f3b9..b518dfb8e 100644 --- a/src/map/channel.h +++ b/src/map/channel.h @@ -88,6 +88,8 @@ struct channel_interface { struct channel_data *(*search) (const char *name, struct map_session_data *sd); struct channel_data *(*create) (enum channel_types type, const char *name, unsigned char color); + void (*delete) (struct channel_data *chan); + 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); enum channel_operation_status (*unban) (struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd); @@ -96,14 +98,15 @@ struct channel_interface { void (*send) (struct channel_data *chan, struct map_session_data *sd, const char *msg); 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); + void (*leave_sub) (struct channel_data *chan, struct map_session_data *sd); void (*quit) (struct map_session_data *sd); - void (*quit_guild) (struct map_session_data *sd); + + void (*map_join) (struct map_session_data *sd); void (*guild_join) (struct guild *g1,struct guild *g2); void (*guild_leave) (struct guild *g1,struct guild *g2); + void (*quit_guild) (struct map_session_data *sd); + void (*config_read) (void); }; diff --git a/src/map/map.c b/src/map/map.c index 4ce581ff2..1f893269b 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1857,10 +1857,6 @@ int map_quit(struct map_session_data *sd) { unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK); } - if (channel->config->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) { - channel->leave(map->list[sd->bl.m].channel,sd); - } - channel->quit(sd); unit->remove_map_pc(sd,CLR_RESPAWN); diff --git a/src/map/pc.c b/src/map/pc.c index a301f8ada..2013bb652 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5043,7 +5043,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int vending->close(sd); } - if (channel->config->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) { + if (map->list[sd->bl.m].channel) { channel->leave(map->list[sd->bl.m].channel,sd); } } -- cgit v1.2.3-60-g2f50