From 35ee16dd3908c021752e439a4fe4ea9e83af9ec0 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 13 Nov 2018 17:38:21 +0100 Subject: Replace sd->channels with a VECTOR This removes some shady array compaction code and prepares the ground for some further fixes. Signed-off-by: Haru --- src/map/atcommand.c | 40 +++++++++++++++++----------------------- src/map/channel.c | 52 ++++++++++++++-------------------------------------- src/map/clif.c | 4 ++-- src/map/pc.c | 1 + src/map/pc.h | 3 +-- src/map/unit.c | 1 + 6 files changed, 36 insertions(+), 65 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 236975b32..adf617ccd 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9019,7 +9019,6 @@ ACMD(channel) { struct channel_data *chan; char subcmd[HCS_NAME_LENGTH], sub1[HCS_NAME_LENGTH], sub2[HCS_NAME_LENGTH], sub3[HCS_NAME_LENGTH]; - unsigned char k = 0; sub1[0] = sub2[0] = sub3[0] = '\0'; if (!*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) { @@ -9056,7 +9055,7 @@ ACMD(channel) } else if (strcmpi(subcmd,"list") == 0) { // sub1 = list type; sub2 = unused; sub3 = unused if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) { - for (k = 0; k < channel->config->colors_count; k++) { + for (int k = 0; k < channel->config->colors_count; k++) { safesnprintf(atcmd_output, sizeof(atcmd_output), "[ %s list colors ] : %s", command, channel->config->colors_name[k]); clif->messagecolor_self(fd, channel->config->colors[k], atcmd_output); @@ -9085,6 +9084,7 @@ ACMD(channel) } } else if (strcmpi(subcmd,"setcolor") == 0) { // sub1 = channel name; sub2 = color; sub3 = unused + int k; if (sub1[0] != '#') { clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#' return false; @@ -9102,10 +9102,7 @@ ACMD(channel) return false; } - for (k = 0; k < channel->config->colors_count; k++) { - if (strcmpi(sub2, channel->config->colors_name[k]) == 0) - break; - } + ARR_FIND(0, channel->config->colors_count, k, strcmpi(sub2, channel->config->colors_name[k]) == 0); if (k == channel->config->colors_count) { safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1411), sub2);// Unknown color '%s' clif->message(fd, atcmd_output); @@ -9116,51 +9113,47 @@ ACMD(channel) clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"leave") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused + int k; if (sub1[0] != '#') { clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#' return false; } - for (k = 0; k < sd->channel_count; k++) { - if (strcmpi(sub1+1,sd->channels[k]->name) == 0) - break; - } - if (k == sd->channel_count) { + ARR_FIND(0, VECTOR_LENGTH(sd->channels), k, strcmpi(sub1 + 1, VECTOR_INDEX(sd->channels, k)->name) == 0); + if (k == VECTOR_LENGTH(sd->channels)) { safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1425),sub1);// You're not part of the '%s' channel clif->message(fd, atcmd_output); return false; } - if (sd->channels[k]->type == HCS_TYPE_ALLY) { + if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) { do { - for (k = 0; k < sd->channel_count; k++) { - if (sd->channels[k]->type == HCS_TYPE_ALLY) { - channel->leave(sd->channels[k],sd); + for (k = 0; k < VECTOR_LENGTH(sd->channels); k++) { + if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) { + channel->leave(VECTOR_INDEX(sd->channels, k), sd); break; } } - } while (k != sd->channel_count); + } while (k != VECTOR_LENGTH(sd->channels)); // FIXME } else { - channel->leave(sd->channels[k],sd); + channel->leave(VECTOR_INDEX(sd->channels, k), sd); } safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1426),sub1); // You've left the '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"bindto") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused + int k; if (sub1[0] != '#') { clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#' return false; } - for (k = 0; k < sd->channel_count; k++) { - if (strcmpi(sub1+1,sd->channels[k]->name) == 0) - break; - } - if (k == sd->channel_count) { + ARR_FIND(0, VECTOR_LENGTH(sd->channels), k, strcmpi(sub1 + 1, VECTOR_INDEX(sd->channels, k)->name) == 0); + if (k == VECTOR_LENGTH(sd->channels)) { safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1425),sub1);// You're not part of the '%s' channel clif->message(fd, atcmd_output); return false; } - sd->gcbind = sd->channels[k]; + sd->gcbind = VECTOR_INDEX(sd->channels, k); safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1431),sub1); // Your global chat is now bound to the '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"unbind") == 0) { @@ -9332,6 +9325,7 @@ ACMD(channel) dbi_destroy(iter); } else if (strcmpi(subcmd,"setopt") == 0) { // sub1 = channel name; sub2 = option name; sub3 = value + int k; const char* opt_str[3] = { "None", "JoinAnnounce", diff --git a/src/map/channel.c b/src/map/channel.c index 3ba56b100..86ca44ea2 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -319,8 +319,8 @@ static void channel_join_sub(struct channel_data *chan, struct map_session_data 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; + VECTOR_ENSURE(sd->channels, 1, 1); + VECTOR_PUSH(sd->channels, chan); if (!stealth && (chan->options&HCS_OPT_ANNOUNCE_JOIN)) { char message[60]; @@ -329,7 +329,7 @@ static void channel_join_sub(struct channel_data *chan, struct map_session_data } /* someone is cheating, we kindly disconnect the bastard */ - if (sd->channel_count > 200) { + if (VECTOR_LENGTH(sd->channels) > 200) { sockt->eof(sd->fd); } @@ -411,32 +411,16 @@ static enum channel_operation_status channel_join(struct channel_data *chan, str */ static void channel_leave_sub(struct channel_data *chan, struct map_session_data *sd) { - unsigned char i; + int i; 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) { - 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; - } + ARR_FIND(0, VECTOR_LENGTH(sd->channels), i, VECTOR_INDEX(sd->channels, i) == chan); + if (i < VECTOR_LENGTH(sd->channels)) { + VECTOR_ERASE(sd->channels, i); } } + /** * Leaves a channel. * @@ -475,14 +459,9 @@ static void channel_leave(struct channel_data *chan, struct map_session_data *sd static void channel_quit(struct map_session_data *sd) { nullpo_retv(sd); - while (sd->channel_count > 0) { + while (VECTOR_LENGTH(sd->channels) > 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; - } + struct channel_data *chan = VECTOR_LAST(sd->channels); channel->leave(chan, sd); } @@ -585,13 +564,11 @@ static void channel_guild_leave_alliance(const struct guild *g_source, const str */ static void channel_quit_guild(struct map_session_data *sd) { - unsigned char i; - nullpo_retv(sd); - for (i = 0; i < sd->channel_count; i++) { - struct channel_data *chan = sd->channels[i]; + for (int i = 0; i < VECTOR_LENGTH(sd->channels); i++) { // FIXME + struct channel_data *chan = VECTOR_INDEX(sd->channels, i); - if (chan == NULL || chan->type != HCS_TYPE_ALLY) + if (chan->type != HCS_TYPE_ALLY) continue; channel->leave(chan, sd); @@ -855,7 +832,6 @@ static void do_final_channel(void) { struct DBIterator *iter = db_iterator(channel->db); struct channel_data *chan; - unsigned char i; for( chan = dbi_first(iter); dbi_exists(iter); chan = dbi_next(iter) ) { channel->delete(chan); @@ -863,7 +839,7 @@ static void do_final_channel(void) dbi_destroy(iter); - for(i = 0; i < channel->config->colors_count; i++) { + for (int i = 0; i < channel->config->colors_count; i++) { aFree(channel->config->colors_name[i]); } diff --git a/src/map/clif.c b/src/map/clif.c index 44cefcd7e..800b13833 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -11083,8 +11083,8 @@ static void clif_parse_WisMessage(int fd, struct map_session_data *sd) if (chan) { int k; - ARR_FIND(0, sd->channel_count, k, sd->channels[k] == chan); - if (k < sd->channel_count || channel->join(chan, sd, "", true) == HCS_STATUS_OK) { + ARR_FIND(0, VECTOR_LENGTH(sd->channels), k, VECTOR_INDEX(sd->channels, k) == chan); + if (k < VECTOR_LENGTH(sd->channels) || channel->join(chan, sd, "", true) == HCS_STATUS_OK) { channel->send(chan,sd,message); } else { clif->message(fd, msg_fd(fd,1402)); //You're not in that channel, type '@join <#channel_name>' diff --git a/src/map/pc.c b/src/map/pc.c index b8a6912ee..282eb7112 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1330,6 +1330,7 @@ static bool pc_authok(struct map_session_data *sd, int login_id2, time_t expirat sd->bg_queue.client_has_bg_data = 0; sd->bg_queue.type = 0; + VECTOR_INIT(sd->channels); VECTOR_INIT(sd->script_queues); VECTOR_INIT(sd->achievement); // Achievements [Smokexyz/Hercules] VECTOR_INIT(sd->storage.item); // initialize storage item vector. diff --git a/src/map/pc.h b/src/map/pc.h index 4ee5f560b..8302279b1 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -557,8 +557,7 @@ END_ZEROED_BLOCK; int shadowform_id; /* [Ind/Hercules] */ - struct channel_data **channels; - unsigned char channel_count; + VECTOR_DECL(struct channel_data *) channels; struct channel_data *gcbind; unsigned char fontcolor; int fontcolor_tid; diff --git a/src/map/unit.c b/src/map/unit.c index 9174bdccd..3c2574111 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2764,6 +2764,7 @@ static int unit_free(struct block_list *bl, clr_type clrtype) aFree(sd->instance); sd->instance = NULL; } + VECTOR_CLEAR(sd->channels); VECTOR_CLEAR(sd->script_queues); VECTOR_CLEAR(sd->achievement); // Achievement [Smokexyz/Hercules] VECTOR_CLEAR(sd->storage.item); -- cgit v1.2.3-60-g2f50 From 60643f1b7bbc2a21f44ab6663dee03d962ff6d6b Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 13 Nov 2018 17:40:48 +0100 Subject: Fix an issue that caused some guild channels not to be left when leaving allychat - The issue was caused by an array compaction while iterating through the array members. - A visible effect was that under certain conditions (depending on the alliance size), a character that left a guild could still see allychat messages from some of the allied guilds. Signed-off-by: Haru --- src/map/atcommand.c | 12 +++++------- src/map/channel.c | 3 ++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index adf617ccd..f46ce0362 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9125,14 +9125,12 @@ ACMD(channel) return false; } if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) { - do { - for (k = 0; k < VECTOR_LENGTH(sd->channels); k++) { - if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) { - channel->leave(VECTOR_INDEX(sd->channels, k), sd); - break; - } + for (k = VECTOR_LENGTH(sd->channels) - 1; k >= 0; k--) { + // Loop downward to avoid issues when channel->leave() compacts the array + if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) { + channel->leave(VECTOR_INDEX(sd->channels, k), sd); } - } while (k != VECTOR_LENGTH(sd->channels)); // FIXME + } } else { channel->leave(VECTOR_INDEX(sd->channels, k), sd); } diff --git a/src/map/channel.c b/src/map/channel.c index 86ca44ea2..e27e9fb0b 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -565,7 +565,8 @@ static void channel_guild_leave_alliance(const struct guild *g_source, const str static void channel_quit_guild(struct map_session_data *sd) { nullpo_retv(sd); - for (int i = 0; i < VECTOR_LENGTH(sd->channels); i++) { // FIXME + for (int i = VECTOR_LENGTH(sd->channels) - 1; i >= 0; i--) { + // Loop downward to avoid issues when channel->leave() compacts the array struct channel_data *chan = VECTOR_INDEX(sd->channels, i); if (chan->type != HCS_TYPE_ALLY) -- cgit v1.2.3-60-g2f50 From d036c82b2080426c03d26f4d7c4015eab1fe1aed Mon Sep 17 00:00:00 2001 From: Mathy Date: Tue, 13 Nov 2018 18:11:08 +0100 Subject: Fixed character not joining its guild chat when joining a new guild. --- src/map/guild.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/map/guild.c b/src/map/guild.c index 757dbb445..17bf7fa6b 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -828,6 +828,11 @@ static int guild_member_added(int guild_id, int account_id, int char_id, int fla //Next line commented because it do nothing, look at guild_recv_info [LuzZza] //clif->charnameupdate(sd); //Update display name [Skotlex] + // Makes the character join their respective guild's channel for #ally chat + if (channel->config->ally && channel->config->ally_autojoin) { + channel->join(g->channel, sd, "", true); + } + return 0; } -- cgit v1.2.3-60-g2f50 From 7c0e13d5eb5385d00f775e692ecc36f7d089615f Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 13 Nov 2018 18:25:39 +0100 Subject: Remove a duplicate output line from the help message for the channel atcommand Signed-off-by: Haru --- src/map/atcommand.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index f46ce0362..50df43266 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -8992,9 +8992,7 @@ static void atcommand_channel_help(int fd, const char *command, bool can_create) clif->message(fd, msg_fd(fd,1428));// - binds global chat to , making anything you type in global be sent to the channel safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1429),command);// -- %s unbind clif->message(fd, atcmd_output); - clif->message(fd, msg_fd(fd,1430));// - unbinds your global chat from its attached channel (if binded) - safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1429),command);// -- %s unbind - clif->message(fd, atcmd_output); + clif->message(fd, msg_fd(fd,1430));// - unbinds your global chat from its attached channel (if bound) if( can_create ) { safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1456),command);// -- %s ban clif->message(fd, atcmd_output); -- cgit v1.2.3-60-g2f50 From 61016983c4eb29dc4a76050fa8920c6bcdc0a1fd Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 13 Nov 2018 18:27:06 +0100 Subject: Fixed code that assumed the character to be already on a map, on login Signed-off-by: Haru --- src/map/pc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/map/pc.c b/src/map/pc.c index 282eb7112..9fa97a729 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5839,8 +5839,11 @@ static int pc_setpos(struct map_session_data *sd, unsigned short map_index, int vending->close(sd); } - if (map->list[sd->bl.m].channel) { - channel->leave(map->list[sd->bl.m].channel,sd); + if (sd->mapindex != 0) { + // Only if the character is already on a map + if (map->list[sd->bl.m].channel) { + channel->leave(map->list[sd->bl.m].channel,sd); + } } } -- cgit v1.2.3-60-g2f50