diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/Makefile.in | 8 | ||||
-rw-r--r-- | src/map/atcommand.c | 278 | ||||
-rw-r--r-- | src/map/channel.c | 833 | ||||
-rw-r--r-- | src/map/channel.h | 119 | ||||
-rw-r--r-- | src/map/clif.c | 613 | ||||
-rw-r--r-- | src/map/clif.h | 67 | ||||
-rw-r--r-- | src/map/guild.c | 60 | ||||
-rw-r--r-- | src/map/instance.c | 3 | ||||
-rw-r--r-- | src/map/irc-bot.c | 54 | ||||
-rw-r--r-- | src/map/irc-bot.h | 6 | ||||
-rw-r--r-- | src/map/map.c | 21 | ||||
-rw-r--r-- | src/map/map.h | 4 | ||||
-rw-r--r-- | src/map/pc.c | 5 | ||||
-rw-r--r-- | src/map/pc.h | 5 | ||||
-rw-r--r-- | src/map/script.c | 26 |
15 files changed, 1203 insertions, 899 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in index ee8b7ac56..90bb55694 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -22,15 +22,15 @@ MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o MT19937AR_H = $(MT19937AR_D)/mt19937ar.h MT19937AR_INCLUDE = -I$(MT19937AR_D) -MAP_C = atcommand.c battle.c battleground.c buyingstore.c chat.c chrif.c \ - clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \ +MAP_C = atcommand.c battle.c battleground.c buyingstore.c channel.c chat.c \ + chrif.c clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \ instance.c intif.c irc-bot.c itemdb.c log.c mail.c map.c mapreg_sql.c \ mercenary.c mob.c npc.c npc_chat.c party.c path.c pc.c pc_groups.c \ pet.c quest.c script.c searchstore.c skill.c status.c storage.c \ trade.c unit.c vending.c MAP_OBJ = $(addprefix obj_sql/, $(patsubst %c,%o,$(MAP_C))) -MAP_H = atcommand.h battle.h battleground.h buyingstore.h chat.h chrif.h \ - clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \ +MAP_H = atcommand.h battle.h battleground.h buyingstore.h channel.h chat.h \ + chrif.h clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \ instance.h intif.h irc-bot.h itemdb.h log.h mail.h map.h mapreg.h \ mercenary.h mob.h npc.h packets.h packets_struct.h party.h path.h \ pc.h pc_groups.h pet.h quest.h script.h searchstore.h skill.h \ diff --git a/src/map/atcommand.c b/src/map/atcommand.c index d75282746..a6e4d7265 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -14,6 +14,7 @@ #include "HPMmap.h" #include "battle.h" +#include "channel.h" #include "chat.h" #include "chrif.h" #include "clif.h" @@ -5461,7 +5462,7 @@ ACMD(autotrade) ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, SCFLAG_NONE); } - clif->chsys_quit(sd); + channel->quit(sd); clif->authfail_fd(sd->fd, 15); @@ -8611,76 +8612,45 @@ ACMD(cart) { #undef MC_CART_MDFY } /* [Ind/Hercules] */ -ACMD(join) { - struct hChSysCh *channel = NULL; - char name[HCHSYS_NAME_LENGTH], pass[HCHSYS_NAME_LENGTH]; +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>) clif->message(fd, atcmd_output); return false; } - if (clif->hChSys->local && strcmpi(name + 1, clif->hChSys->local_name) == 0) { - if( !map->list[sd->bl.m].channel ) { - clif->chsys_mjoin(sd); - if( map->list[sd->bl.m].channel ) /* join might have refused, map has chatting capabilities disabled */ - return true; - } else - channel = map->list[sd->bl.m].channel; - } else if (clif->hChSys->ally && sd->status.guild_id && strcmpi(name + 1, clif->hChSys->ally_name) == 0) { - struct guild *g = sd->guild; - if( !g ) return false;/* unlikely, but we wont let it crash anyway. */ - channel = g->channel; - } else if( !( channel = strdb_get(clif->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; - } - if( !channel ) { + chan = channel->search(name, sd); + + 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(channel->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( channel->pass[0] != '\0' && strcmp(channel->pass,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> <password>) - clif->message(fd, atcmd_output); - return false; - } - } - if( channel->banned && idb_exists(channel->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> <password>) clif->message(fd, atcmd_output); return false; } - if (!(channel->opt & hChSys_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( channel->type == hChSys_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))) { - clif->chsys_join(sg->channel,sd); - } - } - } - } - clif->chsys_join(channel,sd); return true; } @@ -8736,81 +8706,75 @@ static inline void atcmd_channel_help(int fd, const char *command, bool can_crea } /* [Ind/Hercules] */ ACMD(channel) { - struct hChSysCh *channel; - char subcmd[HCHSYS_NAME_LENGTH], sub1[HCHSYS_NAME_LENGTH], sub2[HCHSYS_NAME_LENGTH], sub3[HCHSYS_NAME_LENGTH]; + 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 || !*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) { - atcmd_channel_help(fd,command, (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); + atcmd_channel_help(fd,command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); return true; } - if (strcmpi(subcmd,"create") == 0 && (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) { + 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; - } else if (len < 3 || len > HCHSYS_NAME_LENGTH) { - sprintf(atcmd_output, msg_txt(1406), HCHSYS_NAME_LENGTH);// Channel length must be between 3 and %d + } else if (len < 3 || len > HCS_NAME_LENGTH) { + sprintf(atcmd_output, msg_txt(1406), HCS_NAME_LENGTH);// Channel length must be between 3 and %d clif->message(fd, atcmd_output); return false; } else if (sub3[0] != '\0') { clif->message(fd, msg_txt(1408)); // Channel password may not contain spaces return false; } - if (strcmpi(sub1 + 1, clif->hChSys->local_name) == 0 || strcmpi(sub1 + 1, clif->hChSys->ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1)) { + if (strcmpi(sub1 + 1, channel->config->local_name) == 0 || strcmpi(sub1 + 1, channel->config->ally_name) == 0 || strdb_exists(channel->db, sub1 + 1)) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - CREATE( channel, struct hChSysCh, 1 ); - clif->chsys_create(channel,sub1 + 1,sub2,0); - - channel->owner = sd->status.char_id; - channel->type = hChSys_PRIVATE; - - if( !( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) { - sprintf(atcmd_output, msg_txt(1403),sub1); // You're now in the '%s' channel - clif->message(fd, atcmd_output); - } + chan = channel->create(HCS_TYPE_PRIVATE, sub1 + 1, 0); + channel->set_password(chan, pass); + chan->owner = sd->status.char_id; - clif->chsys_join(channel,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) { char mout[40]; - for (k = 0; k < clif->hChSys->colors_count; k++) { + for (k = 0; k < channel->config->colors_count; k++) { unsigned short msg_len = 1; - msg_len += sprintf(mout, "[ %s list colors ] : %s", command, clif->hChSys->colors_name[k]); + msg_len += sprintf(mout, "[ %s list colors ] : %s", command, channel->config->colors_name[k]); WFIFOHEAD(fd,msg_len + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = clif->hChSys->colors[k]; + WFIFOL(fd,8) = channel->config->colors[k]; safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); WFIFOSET(fd, msg_len + 12); } } else { - DBIterator *iter = db_iterator(clif->channel_db); + DBIterator *iter = db_iterator(channel->db); bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false; clif->message(fd, msg_txt(1410)); // -- Public Channels - if (clif->hChSys->local) { - sprintf(atcmd_output, msg_txt(1409), clif->hChSys->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users ) + if (channel->config->local) { + sprintf(atcmd_output, msg_txt(1409), channel->config->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users ) clif->message(fd, atcmd_output); } - if (clif->hChSys->ally && sd->status.guild_id) { + if (channel->config->ally && sd->status.guild_id) { struct guild *g = sd->guild; if( !g ) { dbi_destroy(iter); return false; } - sprintf(atcmd_output, msg_txt(1409), clif->hChSys->ally_name, db_size(g->channel->users));// - #%s ( %d users ) + sprintf(atcmd_output, msg_txt(1409), channel->config->ally_name, db_size(g->channel->users));// - #%s ( %d users ) clif->message(fd, atcmd_output); } - for (channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) { - if (show_all || channel->type == hChSys_PUBLIC || channel->type == hChSys_IRC) { - sprintf(atcmd_output, msg_txt(1409), channel->name, db_size(channel->users));// - #%s ( %d users ) + for (chan = dbi_first(iter); dbi_exists(iter); chan = dbi_next(iter)) { + if (show_all || chan->type == HCS_TYPE_PUBLIC || chan->type == HCS_TYPE_IRC) { + sprintf(atcmd_output, msg_txt(1409), chan->name, db_size(chan->users));// - #%s ( %d users ) clif->message(fd, atcmd_output); } } @@ -8823,29 +8787,29 @@ ACMD(channel) { return false; } - if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) { + if (!(chan = channel->search(sub1, sd))) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { + if (chan->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } - for (k = 0; k < clif->hChSys->colors_count; k++) { - if (strcmpi(sub2, clif->hChSys->colors_name[k]) == 0) + for (k = 0; k < channel->config->colors_count; k++) { + if (strcmpi(sub2, channel->config->colors_name[k]) == 0) break; } - if (k == clif->hChSys->colors_count) { + if (k == channel->config->colors_count) { sprintf(atcmd_output, msg_txt(1411), sub2);// Unknown color '%s' clif->message(fd, atcmd_output); return false; } - channel->color = k; - sprintf(atcmd_output, msg_txt(1413), sub1, clif->hChSys->colors_name[k]);// '%s' channel color updated to '%s' + chan->color = k; + sprintf(atcmd_output, msg_txt(1413), sub1, channel->config->colors_name[k]);// '%s' channel color updated to '%s' clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"leave") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused @@ -8862,17 +8826,17 @@ ACMD(channel) { clif->message(fd, atcmd_output); return false; } - if (sd->channels[k]->type == hChSys_ALLY) { + if (sd->channels[k]->type == HCS_TYPE_ALLY) { do { for (k = 0; k < sd->channel_count; k++) { - if (sd->channels[k]->type == hChSys_ALLY) { - clif->chsys_left(sd->channels[k],sd); + if (sd->channels[k]->type == HCS_TYPE_ALLY) { + channel->leave(sd->channels[k],sd); break; } } } while (k != sd->channel_count); } else { - clif->chsys_left(sd->channels[k],sd); + channel->leave(sd->channels[k],sd); } sprintf(atcmd_output, msg_txt(1426),sub1); // You've left the '%s' channel clif->message(fd, atcmd_output); @@ -8910,26 +8874,20 @@ ACMD(channel) { } else if (strcmpi(subcmd,"ban") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused struct map_session_data *pl_sd = NULL; - struct hChSysBanEntry *entry = NULL; char sub4[NAME_LENGTH]; ///< player name + enum channel_operation_status ret = HCS_STATUS_OK; if (sub1[0] != '#') { clif->message(fd, msg_txt(1405));// Channel name must start with a '#' return false; } - if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) { + if (!(chan = channel->search(sub1, sd))) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { - sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' - clif->message(fd, atcmd_output); - return false; - } - if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); @@ -8942,25 +8900,24 @@ ACMD(channel) { return false; } - if (pc_has_permission(pl_sd, PC_PERM_HCHSYS_ADMIN)) { - clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user. + ret = channel->ban(chan, sd, pl_sd); + + if (ret == HCS_STATUS_NOPERM) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); return false; } - if (channel->banned && idb_exists(channel->banned,pl_sd->status.account_id)) { + if (ret == HCS_STATUS_ALREADY) { sprintf(atcmd_output, msg_txt(1465), pl_sd->status.name);// Player '%s' is already banned from this channel clif->message(fd, atcmd_output); return false; } - if (!channel->banned) - channel->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA); - - CREATE(entry, struct hChSysBanEntry, 1); - safestrncpy(entry->name, pl_sd->status.name, NAME_LENGTH); - idb_put(channel->banned, pl_sd->status.account_id, entry); - - clif->chsys_left(channel,pl_sd); + if (ret != HCS_STATUS_OK/*ret == HCS_STATUS_FAIL*/) { + clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user. + return false; + } sprintf(atcmd_output, msg_txt(1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel clif->message(fd, atcmd_output); @@ -8968,74 +8925,65 @@ ACMD(channel) { // sub1 = channel name; sub2 = unused; sub3 = unused struct map_session_data *pl_sd = NULL; char sub4[NAME_LENGTH]; ///< player name + enum channel_operation_status ret = HCS_STATUS_OK; if (sub1[0] != '#') { clif->message(fd, msg_txt(1405));// Channel name must start with a '#' return false; } - if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) { + if (!(chan = channel->search(sub1, sd))) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { - sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' - clif->message(fd, atcmd_output); - return false; - } - if (!channel->banned) { - sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players + if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { + sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); return false; } - if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { + if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) { sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); return false; } - if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) { - sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found + ret = channel->unban(chan, sd, pl_sd); + if (ret == HCS_STATUS_NOPERM) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } - if (!idb_exists(channel->banned,pl_sd->status.account_id)) { + if (ret == HCS_STATUS_ALREADY) { sprintf(atcmd_output, msg_txt(1440), pl_sd->status.name);// Player '%s' is not banned from this channel clif->message(fd, atcmd_output); return false; } - idb_remove(channel->banned, pl_sd->status.account_id); - if (!db_size(channel->banned)) { - db_destroy(channel->banned); - channel->banned = NULL; - } - sprintf(atcmd_output, msg_txt(1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"unbanall") == 0) { + enum channel_operation_status ret = HCS_STATUS_OK; // sub1 = channel name; sub2 = unused; sub3 = unused if (sub1[0] != '#') { clif->message(fd, msg_txt(1405));// Channel name must start with a '#' return false; } - if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) { + if (!(chan = channel->search(sub1, sd))) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { + ret = channel->unban(chan, sd, NULL); + if (ret == HCS_STATUS_NOPERM) { sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } - if (!channel->banned) { + if (ret == HCS_STATUS_ALREADY) { sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players clif->message(fd, atcmd_output); return false; } - db_destroy(channel->banned); - channel->banned = NULL; sprintf(atcmd_output, msg_txt(1442),sub1); // Removed all bans from '%s' channel clif->message(fd, atcmd_output); @@ -9049,27 +8997,27 @@ ACMD(channel) { clif->message(fd, msg_txt(1405));// Channel name must start with a '#' return false; } - if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) { + if (!(chan = channel->search(sub1, sd))) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (channel->owner != sd->status.char_id && !isA) { + if (chan->owner != sd->status.char_id && !isA) { sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } - if (!channel->banned) { + if (!chan->banned) { sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players clif->message(fd, atcmd_output); return false; } - sprintf(atcmd_output, msg_txt(1443), channel->name);// -- '%s' ban list + sprintf(atcmd_output, msg_txt(1443), chan->name);// -- '%s' ban list clif->message(fd, atcmd_output); - iter = db_iterator(channel->banned); + iter = db_iterator(chan->banned); for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) { - struct hChSysBanEntry * entry = DB->data2ptr(data); + struct channel_ban_entry *entry = DB->data2ptr(data); if (!isA) sprintf(atcmd_output, msg_txt(1444), entry->name);// - %s %s @@ -9090,12 +9038,12 @@ ACMD(channel) { clif->message(fd, msg_txt(1405));// Channel name must start with a '#' return false; } - if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) { + if (!(chan = channel->search(sub1, sd))) { sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { + if (chan->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; @@ -9119,60 +9067,60 @@ ACMD(channel) { return false; } if (sub3[0] == '\0') { - if (k == hChSys_OPT_MSG_DELAY) { + if (k == HCS_OPT_MSG_DELAY) { sprintf(atcmd_output, msg_txt(1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10) clif->message(fd, atcmd_output); return false; - } else if (channel->opt & k) { + } else if (chan->options & k) { sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel setopt %s 0' clif->message(fd, atcmd_output); return false; } else { - channel->opt |= k; - sprintf(atcmd_output, msg_txt(1450), opt_str[k],channel->name);//option '%s' is now enabled for channel '%s' + channel->set_options(chan, chan->options | k); + sprintf(atcmd_output, msg_txt(1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' clif->message(fd, atcmd_output); return true; } } else { int v = atoi(sub3); - if (k == hChSys_OPT_MSG_DELAY) { + if (k == HCS_OPT_MSG_DELAY) { if (v < 0 || v > 10) { sprintf(atcmd_output, msg_txt(1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10) clif->message(fd, atcmd_output); return false; } if (v == 0) { - channel->opt &=~ k; - channel->msg_delay = 0; - sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name,v);// option '%s' is now disabled for channel '%s' + channel->set_options(chan, chan->options&~k); + chan->msg_delay = 0; + sprintf(atcmd_output, msg_txt(1453), opt_str[k],chan->name,v);// option '%s' is now disabled for channel '%s' clif->message(fd, atcmd_output); return true; } else { - channel->opt |= k; - channel->msg_delay = v; - sprintf(atcmd_output, msg_txt(1452), opt_str[k],channel->name,v);// option '%s' is now enabled for channel '%s' with %d seconds + channel->set_options(chan, chan->options | k); + chan->msg_delay = v; + sprintf(atcmd_output, msg_txt(1452), opt_str[k],chan->name,v);// option '%s' is now enabled for channel '%s' with %d seconds clif->message(fd, atcmd_output); return true; } } else { if (v) { - if (channel->opt & k) { + if (chan->options & k) { sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel opt %s 0' clif->message(fd, atcmd_output); return false; } else { - channel->opt |= k; - sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name);//option '%s' is now enabled for channel '%s' + channel->set_options(chan, chan->options | k); + sprintf(atcmd_output, msg_txt(1454), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' clif->message(fd, atcmd_output); } } else { - if (!(channel->opt & k)) { - sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name); // option '%s' is not enabled on channel '%s' + if (!(chan->options & k)) { + sprintf(atcmd_output, msg_txt(1454), opt_str[k],chan->name); // option '%s' is not enabled on channel '%s' clif->message(fd, atcmd_output); return false; } else { - channel->opt &=~ k; - sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name);// option '%s' is now disabled for channel '%s' + channel->set_options(chan, chan->options&~k); + sprintf(atcmd_output, msg_txt(1453), opt_str[k],chan->name);// option '%s' is now disabled for channel '%s' clif->message(fd, atcmd_output); return true; } @@ -9180,7 +9128,7 @@ ACMD(channel) { } } } else { - atcmd_channel_help(fd, command, (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); + atcmd_channel_help(fd, command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); } return true; } @@ -9191,14 +9139,14 @@ ACMD(fontcolor) { char mout[40]; if( !message || !*message ) { - for( k = 0; k < clif->hChSys->colors_count; k++ ) { - msg_len += sprintf(mout, "[ %s ] : %s", command, clif->hChSys->colors_name[k]); + for( k = 0; k < channel->config->colors_count; k++ ) { + msg_len += sprintf(mout, "[ %s ] : %s", command, channel->config->colors_name[k]); WFIFOHEAD(fd,msg_len + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = clif->hChSys->colors[k]; + WFIFOL(fd,8) = channel->config->colors[k]; safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); WFIFOSET(fd, msg_len + 12); } @@ -9210,24 +9158,24 @@ ACMD(fontcolor) { return true; } - for( k = 0; k < clif->hChSys->colors_count; k++ ) { - if (strcmpi(message, clif->hChSys->colors_name[k]) == 0) + for( k = 0; k < channel->config->colors_count; k++ ) { + if (strcmpi(message, channel->config->colors_name[k]) == 0) break; } - if( k == clif->hChSys->colors_count ) { + if( k == channel->config->colors_count ) { sprintf(atcmd_output, msg_txt(1411), message);// Unknown color '%s' clif->message(fd, atcmd_output); return false; } sd->fontcolor = k + 1; - msg_len += sprintf(mout, "Color changed to '%s'", clif->hChSys->colors_name[k]); + msg_len += sprintf(mout, "Color changed to '%s'", channel->config->colors_name[k]); WFIFOHEAD(fd,msg_len + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = clif->hChSys->colors[k]; + WFIFOL(fd,8) = channel->config->colors[k]; safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); WFIFOSET(fd, msg_len + 12); return true; diff --git a/src/map/channel.c b/src/map/channel.c new file mode 100644 index 000000000..34ce60211 --- /dev/null +++ b/src/map/channel.c @@ -0,0 +1,833 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#define HERCULES_CORE + +#include "channel.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "atcommand.h" +#include "guild.h" +#include "instance.h" +#include "irc-bot.h" +#include "map.h" +#include "pc.h" +#include "../common/cbasetypes.h" +#include "../common/conf.h" +#include "../common/db.h" +#include "../common/malloc.h" +#include "../common/nullpo.h" +#include "../common/random.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/strlib.h" +#include "../common/timer.h" +#include "../common/utils.h" + +struct channel_interface channel_s; + +static struct Channel_Config channel_config; + +/** + * Returns the named channel. + * + * @param name The channel name + * @param sd The issuer character, for character-specific channels (i.e. map, ally) + * @return a pointer to the channel, or NULL. + */ +struct channel_data *channel_search(const char *name, struct map_session_data *sd) +{ + const char *realname = name; + if (!realname || !*realname) + return NULL; + if (*realname == '#') { + realname++; + if (!*realname) + return NULL; + } + + if (channel->config->local && strcmpi(realname, channel->config->local_name) == 0) { + if (!sd) + return NULL; + if (!map->list[sd->bl.m].channel) { + channel->map_join(sd); + } + return map->list[sd->bl.m].channel; + } + + if (channel->config->ally && strcmpi(realname, channel->config->ally_name) == 0) { + if (!sd || !sd->status.guild_id || !sd->guild) + return NULL; + return sd->guild->channel; + } + + return strdb_get(channel->db, realname); +} + +/** + * Creates a chat channel. + * + * If the channel type isn't HCS_TYPE_MAP or HCS_TYPE_ALLY, the channel is added to the channel->db. + * + * @param type The channel type. + * @param name The channel name. + * @param color The channel chat color. + * @return A pointer to the created channel. + */ +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); + safestrncpy(chan->name, name, HCS_NAME_LENGTH); + chan->color = color; + + chan->options = HCS_OPT_BASE; + chan->banned = NULL; + + chan->msg_delay = 0; + + chan->type = type; + if (chan->type != HCS_TYPE_MAP && chan->type != HCS_TYPE_ALLY) + strdb_put(channel->db, chan->name, chan); + 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; + iter = db_iterator(chan->users); + for (sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) { + channel->leave_sub(chan, sd); + } + dbi_destroy(iter); + } + if (chan->banned) { + db_destroy(chan->banned); + chan->banned = NULL; + } + db_destroy(chan->users); + if (chan->m) { + map->list[chan->m].channel = NULL; + aFree(chan); + } else if (chan->type == HCS_TYPE_ALLY) { + aFree(chan); + } else if (!channel->config->closing) { + strdb_remove(channel->db, chan->name); + } +} + +/** + * Sets a chat channel password. + * + * @param chan The channel to edit. + * @param pass The password to set. Pass NULL to remove existing passwords. + */ +void channel_set_password(struct channel_data *chan, const char *password) +{ + nullpo_retv(chan); + if (password) + safestrncpy(chan->password, password, HCS_NAME_LENGTH); + else + chan->password[0] = '\0'; +} + +/** + * Bans a character from the given channel. + * + * @param chan The channel. + * @param ssd The source character, if any. + * @param tsd The target character. + * @retval HCS_STATUS_OK if the operation succeeded. + * @retval HCS_STATUS_ALREADY if the target character is already banned. + * @retval HCS_STATUS_NOPERM if the source character doesn't have enough permissions. + * @retval HCS_STATUS_FAIL in case of generic failure. + */ +enum channel_operation_status channel_ban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd) +{ + struct channel_ban_entry *entry = NULL; + + nullpo_retr(HCS_STATUS_FAIL, chan); + nullpo_retr(HCS_STATUS_FAIL, tsd); + + if (ssd && chan->owner != ssd->status.char_id && !pc_has_permission(ssd, PC_PERM_HCHSYS_ADMIN)) + return HCS_STATUS_NOPERM; + + if (pc_has_permission(tsd, PC_PERM_HCHSYS_ADMIN)) + return HCS_STATUS_FAIL; + + if (chan->banned && idb_exists(chan->banned, tsd->status.account_id)) + return HCS_STATUS_ALREADY; + + if (!chan->banned) + chan->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA); + + CREATE(entry, struct channel_ban_entry, 1); + safestrncpy(entry->name, tsd->status.name, NAME_LENGTH); + idb_put(chan->banned, tsd->status.account_id, entry); + + channel->leave(chan, tsd); + + return HCS_STATUS_OK; +} + +/** + * Unbans a character from the given channel. + * + * @param chan The channel. + * @param ssd The source character, if any. + * @param tsd The target character. If no target character is specified, all characters are unbanned. + * @retval HCS_STATUS_OK if the operation succeeded. + * @retval HCS_STATUS_ALREADY if the target character is not banned. + * @retval HCS_STATUS_NOPERM if the source character doesn't have enough permissions. + * @retval HCS_STATUS_FAIL in case of generic failure. + */ +enum channel_operation_status channel_unban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd) +{ + nullpo_retr(HCS_STATUS_FAIL, chan); + + if (ssd && chan->owner != ssd->status.char_id && !pc_has_permission(ssd, PC_PERM_HCHSYS_ADMIN)) + return HCS_STATUS_NOPERM; + + if (!chan->banned) + return HCS_STATUS_ALREADY; + + if (!tsd) { + // Unban all + db_destroy(chan->banned); + chan->banned = NULL; + return HCS_STATUS_OK; + } + + // Unban one + if (!idb_exists(chan->banned, tsd->status.account_id)) + return HCS_STATUS_ALREADY; + + idb_remove(chan->banned, tsd->status.account_id); + if (!db_size(chan->banned)) { + db_destroy(chan->banned); + chan->banned = NULL; + } + + return HCS_STATUS_OK; +} + +/** + * Sets or edits a channel's options. + * + * @param chan The channel. + * @param options The new options set to apply. + */ +void channel_set_options(struct channel_data *chan, unsigned int options) +{ + nullpo_retv(chan); + + chan->options = options; +} + +/** + * Sends a message to a channel. + * + * @param chan The destination channel. + * @param sd The source character. + * @param msg The message to send. + * + * If no source character is specified, it'll send an anonymous message. + */ +void channel_send(struct channel_data *chan, struct map_session_data *sd, const char *msg) +{ + char message[150]; + nullpo_retv(chan); + + if (sd && chan->msg_delay != 0 + && DIFF_TICK(sd->hchsysch_tick + chan->msg_delay*1000, timer->gettick()) > 0 + && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { + clif->colormes(sd->fd,COLOR_RED,msg_txt(1455)); + return; + } else if (sd) { + snprintf(message, 150, "[ #%s ] %s : %s",chan->name,sd->status.name, msg); + clif->channel_msg(chan,sd,message); + if (chan->type == HCS_TYPE_IRC) + ircbot->relay(sd->status.name,msg); + if (chan->msg_delay != 0) + sd->hchsysch_tick = timer->gettick(); + } else { + snprintf(message, 150, "[ #%s ] %s",chan->name, msg); + clif->channel_msg2(chan, message); + if (chan->type == HCS_TYPE_IRC) + ircbot->relay(NULL, msg); + } +} + +/** + * 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 (!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); + } + + /* someone is cheating, we kindly disconnect the bastard */ + if (sd->channel_count > 200) { + set_eof(sd->fd); + } + +} + +/** + * 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 <x> 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]; + if (chan->type == HCS_TYPE_MAP) { + 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 + } + clif->colormes(sd->fd, COLOR_DEFAULT, 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; +} + +/** + * 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; + + 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; + } + } +} +/** + * 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) +{ + nullpo_retv(chan); + nullpo_retv(sd); + + 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); + } + + 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; + } + + channel->leave(chan, sd); + } +} + +/** + * Joins the local map channel. + * + * @param sd The target character + */ +void channel_map_join(struct map_session_data *sd) +{ + if (sd->state.autotrade || sd->state.standalone) + return; + if (!map->list[sd->bl.m].channel) { + if (map->list[sd->bl.m].flag.chsysnolocalaj || (map->list[sd->bl.m].instance_id >= 0 && instance->list[map->list[sd->bl.m].instance_id].owner_type != IOT_NONE)) + return; + + map->list[sd->bl.m].channel = channel->create(HCS_TYPE_MAP, channel->config->local_name, channel->config->local_color); + map->list[sd->bl.m].channel->m = sd->bl.m; + } + + channel->join(map->list[sd->bl.m].channel, sd, NULL, false); +} + +/** + * Lets a guild's members join a newly allied guild's channel. + * + * Note: g_source members will join g_ally's channel. + * To have g_ally members join g_source's channel, call this function twice, with inverted arguments. + * + * @param g_source Source guild + * @param g_ally Allied guild + */ +void channel_guild_join_alliance(const struct guild *g_source, const struct guild *g_ally) +{ + struct channel_data *chan; + + nullpo_retv(g_source); + nullpo_retv(g_ally); + + if ((chan = g_ally->channel)) { + int i; + for (i = 0; i < g_source->max_member; i++) { + struct map_session_data *sd = g_source->member[i].sd; + if (sd == NULL) + continue; + if (!(g_ally->channel->banned && idb_exists(g_ally->channel->banned, sd->status.account_id))) + channel->join_sub(chan,sd, false); + } + } +} + +/** + * Makes a guild's members leave a no former allied guild's channel. + * + * Note: g_source members will leave g_ally's channel. + * To have g_ally members leave g_source's channel, call this function twice, with inverted arguments. + * + * @param g_source Source guild + * @param g_ally Former allied guild + */ +void channel_guild_leave_alliance(const struct guild *g_source, const struct guild *g_ally) +{ + struct channel_data *chan; + + nullpo_retv(g_source); + nullpo_retv(g_ally); + + if ((chan = g_ally->channel)) { + int i; + for (i = 0; i < g_source->max_member; i++) { + struct map_session_data *sd = g_source->member[i].sd; + if (sd == NULL) + continue; + + channel->leave(chan,sd); + } + } +} + +/** + * Makes a character quit all guild-related channels. + * + * @param sd The character + */ +void channel_quit_guild(struct map_session_data *sd) +{ + unsigned char i; + + for (i = 0; i < sd->channel_count; i++) { + struct channel_data *chan = sd->channels[i]; + + if (chan == NULL || chan->type != HCS_TYPE_ALLY) + continue; + + channel->leave(chan, sd); + } +} + +void read_channels_config(void) +{ + config_t channels_conf; + config_setting_t *chsys = NULL; + const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name + + if (libconfig->read_file(&channels_conf, config_filename)) + return; + + chsys = libconfig->lookup(&channels_conf, "chsys"); + + if (chsys != NULL) { + config_setting_t *settings = libconfig->setting_get_elem(chsys, 0); + config_setting_t *channels; + config_setting_t *colors; + int i,k; + const char *local_name, *ally_name, + *local_color, *ally_color, + *irc_name, *irc_color; + int ally_enabled = 0, local_enabled = 0, + local_autojoin = 0, ally_autojoin = 0, + allow_user_channel_creation = 0, + irc_enabled = 0; + + if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) ) + local_name = "map"; + safestrncpy(channel->config->local_name, local_name, HCS_NAME_LENGTH); + + if( !libconfig->setting_lookup_string(settings, "ally_channel_name", &ally_name) ) + ally_name = "ally"; + safestrncpy(channel->config->ally_name, ally_name, HCS_NAME_LENGTH); + + if( !libconfig->setting_lookup_string(settings, "irc_channel_name", &irc_name) ) + irc_name = "irc"; + safestrncpy(channel->config->irc_name, irc_name, HCS_NAME_LENGTH); + + libconfig->setting_lookup_bool(settings, "map_local_channel", &local_enabled); + libconfig->setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); + libconfig->setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled); + + if (local_enabled) + channel->config->local = true; + if (ally_enabled) + channel->config->ally = true; + if (irc_enabled) + channel->config->irc = true; + + channel->config->irc_server[0] = channel->config->irc_channel[0] = channel->config->irc_nick[0] = channel->config->irc_nick_pw[0] = '\0'; + + if (channel->config->irc) { + const char *irc_server, *irc_channel, + *irc_nick, *irc_nick_pw; + int irc_use_ghost = 0; + if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) { + if( !strstr(irc_server,":") ) { + channel->config->irc = false; + ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n"); + } else { + unsigned char d = 0, dlen = strlen(irc_server); + char server[40]; + if (dlen > 39) + dlen = 39; + memset(server, '\0', sizeof(server)); + + for(d = 0; d < dlen; d++) { + if(irc_server[d] == ':') { + memcpy(server, irc_server, d); + safestrncpy(channel->config->irc_server, server, 40); + memcpy(server, &irc_server[d+1], dlen - d - 1); + channel->config->irc_server_port = atoi(server); + break; + } + } + } + } else { + channel->config->irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n"); + } + if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) ) + safestrncpy(channel->config->irc_channel, irc_channel, 50); + else { + channel->config->irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n"); + } + if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) { + if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) { + sprintf(channel->config->irc_nick, "Hercules_chSysBot%d",rnd()%777); + } else + safestrncpy(channel->config->irc_nick, irc_nick, 40); + } else { + channel->config->irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n"); + } + if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) { + safestrncpy(channel->config->irc_nick_pw, irc_nick_pw, 30); + config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost); + channel->config->irc_use_ghost = irc_use_ghost; + } + + } + + libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); + libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); + + if (local_autojoin) + channel->config->local_autojoin = true; + if (ally_autojoin) + channel->config->ally_autojoin = true; + + libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); + + if( allow_user_channel_creation ) + channel->config->allow_user_channel_creation = true; + + if( (colors = libconfig->setting_get_member(settings, "colors")) != NULL ) { + int color_count = libconfig->setting_length(colors); + CREATE(channel->config->colors, unsigned int, color_count); + CREATE(channel->config->colors_name, char *, color_count); + for(i = 0; i < color_count; i++) { + config_setting_t *color = libconfig->setting_get_elem(colors, i); + + CREATE(channel->config->colors_name[i], char, HCS_NAME_LENGTH); + + safestrncpy(channel->config->colors_name[i], config_setting_name(color), HCS_NAME_LENGTH); + + channel->config->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0); + channel->config->colors[i] = (channel->config->colors[i] & 0x0000FF) << 16 | (channel->config->colors[i] & 0x00FF00) | (channel->config->colors[i] & 0xFF0000) >> 16;//RGB to BGR + } + channel->config->colors_count = color_count; + } + + libconfig->setting_lookup_string(settings, "map_local_channel_color", &local_color); + + for (k = 0; k < channel->config->colors_count; k++) { + if (strcmpi(channel->config->colors_name[k], local_color) == 0) + break; + } + + if (k < channel->config->colors_count) { + channel->config->local_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); + channel->config->local = false; + } + + libconfig->setting_lookup_string(settings, "ally_channel_color", &ally_color); + + for (k = 0; k < channel->config->colors_count; k++) { + if (strcmpi(channel->config->colors_name[k], ally_color) == 0) + break; + } + + if( k < channel->config->colors_count ) { + channel->config->ally_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name); + channel->config->ally = false; + } + + libconfig->setting_lookup_string(settings, "irc_channel_color", &irc_color); + + for (k = 0; k < channel->config->colors_count; k++) { + if (strcmpi(channel->config->colors_name[k], irc_color) == 0) + break; + } + + if (k < channel->config->colors_count) { + channel->config->irc_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name); + channel->config->irc = false; + } + + if (channel->config->irc) { + ircbot->channel = channel->create(HCS_TYPE_IRC, channel->config->irc_name, channel->config->irc_color); + } + + if( (channels = libconfig->setting_get_member(settings, "default_channels")) != NULL ) { + int channel_count = libconfig->setting_length(channels); + + for(i = 0; i < channel_count; i++) { + config_setting_t *chan = libconfig->setting_get_elem(channels, i); + const char *name = config_setting_name(chan); + const char *color = libconfig->setting_get_string_elem(channels,i); + + ARR_FIND(0, channel->config->colors_count, k, strcmpi(channel->config->colors_name[k],color) == 0); + if (k == channel->config->colors_count) { + ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); + continue; + } + if (strcmpi(name, channel->config->local_name) == 0 + || strcmpi(name, channel->config->ally_name) == 0 + || strcmpi(name, channel->config->irc_name) == 0 + || strdb_exists(channel->db, name)) { + ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); + continue; + + } + channel->create(HCS_TYPE_PUBLIC, name, k); + } + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel->db), config_filename); + libconfig->destroy(&channels_conf); + } +} + +/*========================================== + * + *------------------------------------------*/ +int do_init_channel(bool minimal) +{ + if (minimal) + return 0; + + channel->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCS_NAME_LENGTH); + channel->config->ally = channel->config->local = channel->config->irc = channel->config->ally_autojoin = channel->config->local_autojoin = false; + channel->config_read(); + + return 0; +} + +void do_final_channel(void) +{ + 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); + } + + dbi_destroy(iter); + + for(i = 0; i < channel->config->colors_count; i++) { + aFree(channel->config->colors_name[i]); + } + + if (channel->config->colors_count) { + aFree(channel->config->colors_name); + aFree(channel->config->colors); + } + + db_destroy(channel->db); +} + +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->search = channel_search; + channel->create = channel_create; + channel->delete = channel_delete; + + channel->set_password = channel_set_password; + channel->ban = channel_ban; + channel->unban = channel_unban; + 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->leave_sub = channel_leave_sub; + channel->quit = channel_quit; + + channel->map_join = channel_map_join; + channel->guild_join_alliance = channel_guild_join_alliance; + channel->guild_leave_alliance = channel_guild_leave_alliance; + channel->quit_guild = channel_quit_guild; + + channel->config_read = read_channels_config; +} diff --git a/src/map/channel.h b/src/map/channel.h new file mode 100644 index 000000000..ba6aafc79 --- /dev/null +++ b/src/map/channel.h @@ -0,0 +1,119 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef MAP_CHANNEL_H +#define MAP_CHANNEL_H + +#include <stdarg.h> + +#include "map.h" +#include "../common/cbasetypes.h" +#include "../common/db.h" + +/** + * Declarations + **/ +struct map_session_data; +struct guild; + +/** + * Defines + **/ +#define HCS_NAME_LENGTH 20 + +enum channel_options { + HCS_OPT_BASE = 0x0, + HCS_OPT_ANNOUNCE_JOIN = 0x1, + HCS_OPT_MSG_DELAY = 0x2, +}; + +enum channel_types { + HCS_TYPE_PUBLIC = 0, + HCS_TYPE_PRIVATE = 1, + HCS_TYPE_MAP = 2, + HCS_TYPE_ALLY = 3, + HCS_TYPE_IRC = 4, +}; + +enum channel_operation_status { + HCS_STATUS_OK = 0, + HCS_STATUS_FAIL, + HCS_STATUS_ALREADY, + HCS_STATUS_NOPERM, + HCS_STATUS_BANNED, +}; + +/** + * Structures + **/ +struct Channel_Config { + unsigned int *colors; + char **colors_name; + unsigned char colors_count; + bool local, ally, irc; + bool local_autojoin, ally_autojoin; + char local_name[HCS_NAME_LENGTH], ally_name[HCS_NAME_LENGTH], irc_name[HCS_NAME_LENGTH]; + unsigned char local_color, ally_color, irc_color; + bool closing; + bool allow_user_channel_creation; + char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30]; + unsigned short irc_server_port; + bool irc_use_ghost; +}; + +struct channel_ban_entry { + char name[NAME_LENGTH]; +}; + +struct channel_data { + char name[HCS_NAME_LENGTH]; + char password[HCS_NAME_LENGTH]; + unsigned char color; + DBMap *users; + DBMap *banned; + unsigned int options; + unsigned int owner; + enum channel_types type; + uint16 m; + unsigned char msg_delay; +}; + +struct channel_interface { + /* vars */ + DBMap *db; + struct Channel_Config *config; + + int (*init) (bool minimal); + void (*final) (void); + + 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); + 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_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 (*leave_sub) (struct channel_data *chan, struct map_session_data *sd); + void (*quit) (struct map_session_data *sd); + + void (*map_join) (struct map_session_data *sd); + void (*guild_join_alliance) (const struct guild *g_source, const struct guild *g_ally); + void (*guild_leave_alliance) (const struct guild *g_source, const struct guild *g_ally); + void (*quit_guild) (struct map_session_data *sd); + + void (*config_read) (void); +}; + +struct channel_interface *channel; + +#ifdef HERCULES_CORE +void channel_defaults(void); +#endif // HERCULES_CORE + +#endif /* MAP_CHANNEL_H */ diff --git a/src/map/clif.c b/src/map/clif.c index 291b5cb46..269b72ae1 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16,6 +16,7 @@ #include "atcommand.h" #include "battle.h" #include "battleground.h" +#include "channel.h" #include "chat.h" #include "chrif.h" #include "elemental.h" @@ -72,8 +73,6 @@ static struct packet_npc_market_open npcmarket_open; //#define DUMP_UNKNOWN_PACKET //#define DUMP_INVALID_PACKET -static struct hChSysConfig clif_hChSys; - //Converts item type in case of pet eggs. static inline int itemtype(int type) { switch( type ) { @@ -1833,24 +1832,6 @@ void clif_buylist(struct map_session_data *sd, struct npc_data *nd) { WFIFOW(fd,2) = 4 + c*11; WFIFOSET(fd,WFIFOW(fd,2)); } -void clif_hercules_chsys_create(struct hChSysCh *channel, char *name, char *pass, unsigned char color) { - channel->users = idb_alloc(DB_OPT_BASE); - if( name ) - safestrncpy(channel->name, name, HCHSYS_NAME_LENGTH); - channel->color = color; - if( !pass ) - channel->pass[0] = '\0'; - else - safestrncpy(channel->pass, pass, HCHSYS_NAME_LENGTH); - - channel->opt = hChSys_OPT_BASE; - channel->banned = NULL; - - channel->msg_delay = 0; - - if( channel->type != hChSys_MAP && channel->type != hChSys_ALLY ) - strdb_put(clif->channel_db, channel->name, channel); -} /// Presents list of items, that can be sold to an NPC shop (ZC_PC_SELL_ITEMLIST). /// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }* @@ -2116,27 +2097,7 @@ void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, in WFIFOL(fd,19)=color; WFIFOSET(fd,packet_len(0x144)); } -void clif_hercules_chsys_join(struct hChSysCh *channel, struct map_session_data *sd) { - if( idb_put(channel->users, sd->status.char_id, sd) ) - return; - RECREATE(sd->channels, struct hChSysCh *, ++sd->channel_count); - sd->channels[ sd->channel_count - 1 ] = channel; - - if( sd->stealth ) { - sd->stealth = false; - } else if( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) { - char message[60]; - sprintf(message, "#%s '%s' joined",channel->name,sd->status.name); - clif->chsys_msg(channel,sd,message); - } - - /* someone is cheating, we kindly disconnect the bastard */ - if( sd->channel_count > 200 ) { - set_eof(sd->fd); - } - -} /// Displays an illustration image. /// 0145 <image name>.16B <type>.B (ZC_SHOW_IMAGE) /// 01b3 <image name>.64B <type>.B (ZC_SHOW_IMAGE2) @@ -2669,225 +2630,6 @@ void clif_guild_xy_remove(struct map_session_data *sd) WBUFW(buf,8)=-1; clif->send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); } -void read_channels_config(void) { - config_t channels_conf; - config_setting_t *chsys = NULL; - const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name - - if (libconfig->read_file(&channels_conf, config_filename)) - return; - - chsys = libconfig->lookup(&channels_conf, "chsys"); - - if (chsys != NULL) { - config_setting_t *settings = libconfig->setting_get_elem(chsys, 0); - config_setting_t *channels; - config_setting_t *colors; - int i,k; - const char *local_name, *ally_name, - *local_color, *ally_color, - *irc_name, *irc_color; - int ally_enabled = 0, local_enabled = 0, - local_autojoin = 0, ally_autojoin = 0, - allow_user_channel_creation = 0, - irc_enabled = 0; - - if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) ) - local_name = "map"; - safestrncpy(clif->hChSys->local_name, local_name, HCHSYS_NAME_LENGTH); - - if( !libconfig->setting_lookup_string(settings, "ally_channel_name", &ally_name) ) - ally_name = "ally"; - safestrncpy(clif->hChSys->ally_name, ally_name, HCHSYS_NAME_LENGTH); - - if( !libconfig->setting_lookup_string(settings, "irc_channel_name", &irc_name) ) - irc_name = "irc"; - safestrncpy(clif->hChSys->irc_name, irc_name, HCHSYS_NAME_LENGTH); - - libconfig->setting_lookup_bool(settings, "map_local_channel", &local_enabled); - libconfig->setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); - libconfig->setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled); - - if (local_enabled) - clif->hChSys->local = true; - if (ally_enabled) - clif->hChSys->ally = true; - if (irc_enabled) - clif->hChSys->irc = true; - - clif->hChSys->irc_server[0] = clif->hChSys->irc_channel[0] = clif->hChSys->irc_nick[0] = clif->hChSys->irc_nick_pw[0] = '\0'; - - if (clif->hChSys->irc) { - const char *irc_server, *irc_channel, - *irc_nick, *irc_nick_pw; - int irc_use_ghost = 0; - if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) { - if( !strstr(irc_server,":") ) { - clif->hChSys->irc = false; - ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n"); - } else { - unsigned char d = 0, dlen = strlen(irc_server); - char server[40]; - if (dlen > 39) - dlen = 39; - memset(server, '\0', sizeof(server)); - - for(d = 0; d < dlen; d++) { - if(irc_server[d] == ':') { - memcpy(server, irc_server, d); - safestrncpy(clif->hChSys->irc_server, server, 40); - memcpy(server, &irc_server[d+1], dlen - d - 1); - clif->hChSys->irc_server_port = atoi(server); - break; - } - } - } - } else { - clif->hChSys->irc = false; - ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n"); - } - if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) ) - safestrncpy(clif->hChSys->irc_channel, irc_channel, 50); - else { - clif->hChSys->irc = false; - ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n"); - } - if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) { - if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) { - sprintf(clif->hChSys->irc_nick, "Hercules_chSysBot%d",rnd()%777); - } else - safestrncpy(clif->hChSys->irc_nick, irc_nick, 40); - } else { - clif->hChSys->irc = false; - ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n"); - } - if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) { - safestrncpy(clif->hChSys->irc_nick_pw, irc_nick_pw, 30); - config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost); - clif->hChSys->irc_use_ghost = irc_use_ghost; - } - - } - - libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); - libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); - - if (local_autojoin) - clif->hChSys->local_autojoin = true; - if (ally_autojoin) - clif->hChSys->ally_autojoin = true; - - libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); - - if( allow_user_channel_creation ) - clif->hChSys->allow_user_channel_creation = true; - - if( (colors = libconfig->setting_get_member(settings, "colors")) != NULL ) { - int color_count = libconfig->setting_length(colors); - CREATE(clif->hChSys->colors, unsigned int, color_count); - CREATE(clif->hChSys->colors_name, char *, color_count); - for(i = 0; i < color_count; i++) { - config_setting_t *color = libconfig->setting_get_elem(colors, i); - - CREATE(clif->hChSys->colors_name[i], char, HCHSYS_NAME_LENGTH); - - safestrncpy(clif->hChSys->colors_name[i], config_setting_name(color), HCHSYS_NAME_LENGTH); - - clif->hChSys->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0); - clif->hChSys->colors[i] = (clif->hChSys->colors[i] & 0x0000FF) << 16 | (clif->hChSys->colors[i] & 0x00FF00) | (clif->hChSys->colors[i] & 0xFF0000) >> 16;//RGB to BGR - } - clif->hChSys->colors_count = color_count; - } - - libconfig->setting_lookup_string(settings, "map_local_channel_color", &local_color); - - for (k = 0; k < clif->hChSys->colors_count; k++) { - if (strcmpi(clif->hChSys->colors_name[k], local_color) == 0) - break; - } - - if (k < clif->hChSys->colors_count) { - clif->hChSys->local_color = k; - } else { - ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); - clif->hChSys->local = false; - } - - libconfig->setting_lookup_string(settings, "ally_channel_color", &ally_color); - - for (k = 0; k < clif->hChSys->colors_count; k++) { - if (strcmpi(clif->hChSys->colors_name[k], ally_color) == 0) - break; - } - - if( k < clif->hChSys->colors_count ) { - clif->hChSys->ally_color = k; - } else { - ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name); - clif->hChSys->ally = false; - } - - libconfig->setting_lookup_string(settings, "irc_channel_color", &irc_color); - - for (k = 0; k < clif->hChSys->colors_count; k++) { - if (strcmpi(clif->hChSys->colors_name[k], irc_color) == 0) - break; - } - - if (k < clif->hChSys->colors_count) { - clif->hChSys->irc_color = k; - } else { - ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name); - clif->hChSys->irc = false; - } - - if (clif->hChSys->irc) { - struct hChSysCh *chd; - CREATE(chd, struct hChSysCh, 1); - - safestrncpy(chd->name, clif->hChSys->irc_name, HCHSYS_NAME_LENGTH); - chd->type = hChSys_IRC; - - clif->chsys_create(chd, NULL, NULL, clif->hChSys->irc_color); - ircbot->channel = chd; - } - - if( (channels = libconfig->setting_get_member(settings, "default_channels")) != NULL ) { - int channel_count = libconfig->setting_length(channels); - - for(i = 0; i < channel_count; i++) { - config_setting_t *channel = libconfig->setting_get_elem(channels, i); - const char *name = config_setting_name(channel); - const char *color = libconfig->setting_get_string_elem(channels,i); - struct hChSysCh *chd; - - for (k = 0; k < clif->hChSys->colors_count; k++) { - if (strcmpi(clif->hChSys->colors_name[k],color) == 0) - break; - } - if( k == clif->hChSys->colors_count) { - ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); - continue; - } - if( strcmpi(name, clif->hChSys->local_name) == 0 || strcmpi(name, clif->hChSys->ally_name) == 0 || strcmpi(name, clif->hChSys->irc_name) == 0 || strdb_exists(clif->channel_db, name) ) { - ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); - continue; - - } - CREATE( chd, struct hChSysCh, 1 ); - - safestrncpy(chd->name, name, HCHSYS_NAME_LENGTH); - chd->type = hChSys_PUBLIC; - - clif->chsys_create(chd,NULL,NULL,k); - } - } - - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(clif->channel_db), config_filename); - libconfig->destroy(&channels_conf); - } -} - /*========================================== * @@ -3711,21 +3453,6 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) } } -void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data *sd, const char *msg) { - if( channel->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + ( channel->msg_delay * 1000 ), timer->gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { - clif->colormes(sd->fd,COLOR_RED,msg_txt(1455)); - return; - } else { - char message[150]; - snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg); - clif->chsys_msg(channel,sd,message); - if( channel->type == hChSys_IRC ) - ircbot->relay(sd->status.name,msg); - if( channel->msg_delay != 0 ) - sd->hchsysch_tick = timer->gettick(); - } -} - /// Inform client whether chatroom creation was successful or not (ZC_ACK_CREATE_CHATROOM). /// 00d6 <flag>.B /// flag: @@ -9125,8 +8852,9 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_, return true; } -void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *sd, char *msg) { - DBIterator *iter = db_iterator(channel->users); +void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg) +{ + DBIterator *iter = db_iterator(chan->users); struct map_session_data *user; unsigned short msg_len = strlen(msg) + 1; @@ -9134,10 +8862,10 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data * WFIFOW(sd->fd,0) = 0x2C1; WFIFOW(sd->fd,2) = msg_len + 12; WFIFOL(sd->fd,4) = 0; - WFIFOL(sd->fd,8) = clif->hChSys->colors[channel->color]; + WFIFOL(sd->fd,8) = channel->config->colors[chan->color]; safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); - for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) { + for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { if( user->fd == sd->fd ) continue; WFIFOHEAD(user->fd,msg_len + 12); @@ -9150,8 +8878,9 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data * dbi_destroy(iter); } -void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) { - DBIterator *iter = db_iterator(channel->users); +void clif_channel_msg2(struct channel_data *chan, char *msg) +{ + DBIterator *iter = db_iterator(chan->users); struct map_session_data *user; unsigned char buf[210]; unsigned short msg_len = strlen(msg) + 1; @@ -9159,10 +8888,10 @@ void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) { WBUFW(buf,0) = 0x2C1; WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = 0; - WBUFL(buf,8) = clif->hChSys->colors[channel->color]; + WBUFL(buf,8) = channel->config->colors[chan->color]; safestrncpy((char*)WBUFP(buf,12), msg, msg_len); - for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) { + for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { WFIFOHEAD(user->fd,msg_len + 12); memcpy(WFIFOP(user->fd,0), WBUFP(buf,0), msg_len + 12); WFIFOSET(user->fd, msg_len + 12); @@ -9251,34 +8980,6 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { chrif->authreq(sd,false); } -void clif_hercules_chsys_mjoin(struct map_session_data *sd) { - if( sd->state.autotrade || sd->state.standalone ) - return; - if( !map->list[sd->bl.m].channel ) { - - if (map->list[sd->bl.m].flag.chsysnolocalaj || (map->list[sd->bl.m].instance_id >= 0 && instance->list[map->list[sd->bl.m].instance_id].owner_type != IOT_NONE) ) - return; - - CREATE(map->list[sd->bl.m].channel, struct hChSysCh , 1); - safestrncpy(map->list[sd->bl.m].channel->name, clif->hChSys->local_name, HCHSYS_NAME_LENGTH); - map->list[sd->bl.m].channel->type = hChSys_MAP; - map->list[sd->bl.m].channel->m = sd->bl.m; - - clif->chsys_create(map->list[sd->bl.m].channel, NULL, NULL, clif->hChSys->local_color); - } - - if( map->list[sd->bl.m].channel->banned && idb_exists(map->list[sd->bl.m].channel->banned, sd->status.account_id) ) { - return; - } - - clif->chsys_join(map->list[sd->bl.m].channel,sd); - - if( !( map->list[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) { - char mout[60]; - sprintf(mout, msg_txt(1435), clif->hChSys->local_name, map->list[sd->bl.m].name); // You're now in the '#%s' channel for '%s' - clif->colormes(sd->fd, COLOR_DEFAULT, mout); - } -} /// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT). /// 007d @@ -9550,8 +9251,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { status_calc_pc(sd, SCO_NONE);/* some conditions are map-dependent so we must recalculate */ sd->state.changemap = false; - if (clif->hChSys->local && clif->hChSys->local_autojoin) { - clif->chsys_mjoin(sd); + if (channel->config->local && channel->config->local_autojoin) { + channel->map_join(sd); } } @@ -9927,7 +9628,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) sd->idletime = sockt->last_tick; if( sd->gcbind ) { - clif->chsys_send(sd->gcbind,sd,message); + channel->send(sd->gcbind,sd,message); return; } else if ( sd->fontcolor && !sd->chatID ) { char mout[200]; @@ -9953,7 +9654,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = mylen + 12; WFIFOL(fd,4) = sd->bl.id; - WFIFOL(fd,8) = clif->hChSys->colors[sd->fontcolor - 1]; + WFIFOL(fd,8) = channel->config->colors[sd->fontcolor - 1]; safestrncpy((char*)WFIFOP(fd,12), mout, mylen); clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); WFIFOL(fd,4) = -sd->bl.id; @@ -10219,117 +9920,6 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, } } -void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data *sd) { - unsigned char i; - - if ( !idb_remove(channel->users,sd->status.char_id) ) - return; - - if( channel == sd->gcbind ) - sd->gcbind = NULL; - - if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) { - clif->chsys_delete(channel); - } else if( !clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) { - char message[60]; - sprintf(message, "#%s '%s' left",channel->name,sd->status.name); - clif->chsys_msg(channel,sd,message); - } - - for( i = 0; i < sd->channel_count; i++ ) { - if( sd->channels[i] == channel ) { - 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; - } - } - -} - -void clif_hercules_chsys_quitg(struct map_session_data *sd) { - unsigned char i; - - for( i = 0; i < sd->channel_count; i++ ) { - struct hChSysCh *channel = sd->channels[i]; - if (channel != NULL && channel->type == hChSys_ALLY) { - if (!idb_remove(channel->users,sd->status.char_id)) - continue; - - if( channel == sd->gcbind ) - sd->gcbind = NULL; - - if (!db_size(channel->users) && channel->type == hChSys_PRIVATE) { - clif->chsys_delete(channel); - } else if (!clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) { - char message[60]; - sprintf(message, "#%s '%s' left",channel->name,sd->status.name); - clif->chsys_msg(channel,sd,message); - } - sd->channels[i] = NULL; - } - } - - 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; - } - } - -} - - -void clif_hercules_chsys_quit(struct map_session_data *sd) { - unsigned char i; - - for (i = 0; i < sd->channel_count; i++) { - struct hChSysCh *channel = sd->channels[i]; - if (channel != NULL) { - idb_remove(channel->users,sd->status.char_id); - - if( channel == sd->gcbind ) - sd->gcbind = NULL; - - if (!db_size(channel->users) && channel->type == hChSys_PRIVATE) { - clif->chsys_delete(channel); - } else if (!clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) { - char message[60]; - sprintf(message, "#%s '%s' left",channel->name,sd->status.name); - clif->chsys_msg(channel,sd,message); - } - - } - } - - sd->channel_count = 0; - aFree(sd->channels); - sd->channels = NULL; -} - /// Request for an action. /// 0089 <target id>.L <action>.B (CZ_REQUEST_ACT) /// 0437 <target id>.L <action>.B (CZ_REQUEST_ACT2) @@ -10450,42 +10040,14 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) return; } } else if( target[0] == '#' ) { - struct hChSysCh *channel = NULL; - char* chname = target; + char *chname = target; + struct channel_data *chan = channel->search(chname, sd); - chname++; - - if (clif->hChSys->local && strcmpi(chname, clif->hChSys->local_name) == 0) { - if( !map->list[sd->bl.m].channel ) { - clif->chsys_mjoin(sd); - } - channel = map->list[sd->bl.m].channel; - } else if (clif->hChSys->ally && sd->status.guild_id && strcmpi(chname, clif->hChSys->ally_name) == 0) { - struct guild *g = sd->guild; - if( !g ) return; - channel = g->channel; - } - if( channel || (channel = strdb_get(clif->channel_db,chname)) ) { + if (chan) { int k; - for( k = 0; k < sd->channel_count; k++ ) { - if( sd->channels[k] == channel ) - break; - } - if( k < sd->channel_count ) { - clif->chsys_send(channel,sd,message); - } else if( channel->pass[0] == '\0' && !(channel->banned && idb_exists(channel->banned, sd->status.account_id)) ) { - if( channel->type == hChSys_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))) - clif->chsys_join(sg->channel,sd); - } - } - } - clif->chsys_join(channel,sd); - clif->chsys_send(channel,sd,message); + ARR_FIND(0, sd->channel_count, k, sd->channels[k] == chan); + if (k < sd->channel_count || channel->join(chan, sd, NULL, true) == HCS_STATUS_OK) { + channel->send(chan,sd,message); } else { clif->message(fd, msg_txt(1402)); } @@ -10711,95 +10273,6 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) { pc->equipitem(sd,p->index,p->wearLocation); } -void clif_hercules_chsys_delete(struct hChSysCh *channel) { - if (db_size(channel->users) && !clif->hChSys->closing) { - DBIterator *iter; - struct map_session_data *sd; - unsigned char i; - iter = db_iterator(channel->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] == channel ) { - 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; - } - } - } - dbi_destroy(iter); - } - if( channel->banned ) { - db_destroy(channel->banned); - channel->banned = NULL; - } - db_destroy(channel->users); - if( channel->m ) { - map->list[channel->m].channel = NULL; - aFree(channel); - } else if ( channel->type == hChSys_ALLY ) - aFree(channel); - else if (!clif->hChSys->closing) - strdb_remove(clif->channel_db, channel->name); -} -void clif_hercules_chsys_gjoin(struct guild *g1,struct guild *g2) { - struct map_session_data *sd; - struct hChSysCh *channel; - int j; - - if( (channel = g1->channel) ) { - 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))) - clif->chsys_join(channel,sd); - } - } - } - - if( (channel = g2->channel) ) { - 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))) - clif->chsys_join(channel,sd); - } - } - } -} -void clif_hercules_chsys_gleave(struct guild *g1,struct guild *g2) { - struct map_session_data *sd; - struct hChSysCh *channel; - int j; - - if( (channel = g1->channel) ) { - for(j = 0; j < g2->max_member; j++) { - if( (sd = g2->member[j].sd) != NULL ) { - clif->chsys_left(channel,sd); - } - } - } - - if( (channel = g2->channel) ) { - for(j = 0; j < g1->max_member; j++) { - if( (sd = g1->member[j].sd) != NULL ) { - clif->chsys_left(channel,sd); - } - } - } -} - /// Request to take off an equip (CZ_REQ_TAKEOFF_EQUIP). /// 00ab <index>.W void clif_parse_UnequipItem(int fd,struct map_session_data *sd) @@ -18899,34 +18372,13 @@ int do_init_clif(bool minimal) { clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR); - clif->channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCHSYS_NAME_LENGTH); - clif->hChSys->ally = clif->hChSys->local = clif->hChSys->irc = clif->hChSys->ally_autojoin = clif->hChSys->local_autojoin = false; - clif->chann_config_read(); - return 0; } -void do_final_clif(void) { - DBIterator *iter = db_iterator(clif->channel_db); - struct hChSysCh *channel; +void do_final_clif(void) +{ unsigned char i; - for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) { - clif->chsys_delete(channel); - } - - dbi_destroy(iter); - - for(i = 0; i < clif->hChSys->colors_count; i++) { - aFree(clif->hChSys->colors_name[i]); - } - - if (clif->hChSys->colors_count) { - aFree(clif->hChSys->colors_name); - aFree(clif->hChSys->colors); - } - - db_destroy(clif->channel_db); ers_destroy(clif->delay_clearunit_ers); ers_destroy(clif->delayed_damage_ers); @@ -19420,21 +18872,11 @@ void clif_defaults(void) { clif->user_count = clif_user_count; clif->noask_sub = clif_noask_sub; clif->bc_ready = clif_bc_ready; - clif->undisguise_timer = clif_undisguise_timer; /* Hercules Channel System */ - clif->hChSys = &clif_hChSys; - clif->chsys_create = clif_hercules_chsys_create; - clif->chsys_msg = clif_hercules_chsys_msg; - clif->chsys_msg2 = clif_hercules_chsys_msg2; - clif->chsys_send = clif_hercules_chsys_send; - clif->chsys_join = clif_hercules_chsys_join; - clif->chsys_left = clif_hercules_chsys_left; - clif->chsys_delete = clif_hercules_chsys_delete; - clif->chsys_mjoin = clif_hercules_chsys_mjoin; - clif->chsys_quit = clif_hercules_chsys_quit; - clif->chsys_quitg = clif_hercules_chsys_quitg; - clif->chsys_gjoin = clif_hercules_chsys_gjoin; - clif->chsys_gleave = clif_hercules_chsys_gleave; + clif->channel_msg = clif_channel_msg; + clif->channel_msg2 = clif_channel_msg2; + /* */ + clif->undisguise_timer = clif_undisguise_timer; /* Bank System [Yommy/Hercules] */ clif->bank_deposit = clif_bank_deposit; clif->bank_withdraw = clif_bank_withdraw; @@ -19488,7 +18930,6 @@ void clif_defaults(void) { clif->pKickFromChat = clif_parse_KickFromChat; clif->pChatLeave = clif_parse_ChatLeave; clif->pTradeRequest = clif_parse_TradeRequest; - clif->chann_config_read = read_channels_config; clif->pTradeAck = clif_parse_TradeAck; clif->pTradeAddItem = clif_parse_TradeAddItem; clif->pTradeOk = clif_parse_TradeOk; diff --git a/src/map/clif.h b/src/map/clif.h index 6a99ba79a..5f1a2a899 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -38,6 +38,7 @@ struct party_booking_ad_info; struct view_data; struct eri; struct skill_cd; +struct channel_data; /** * Defines @@ -47,7 +48,6 @@ struct skill_cd; #define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0) #define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF ) #define clif_viewequip_fail( sd ) clif->msg( (sd), 0x54d ); -#define HCHSYS_NAME_LENGTH 20 #define MAX_ROULETTE_LEVEL 7 /** client-defined value **/ #define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/ @@ -375,20 +375,6 @@ enum clif_colors { COLOR_MAX }; -enum hChSysChOpt { - hChSys_OPT_BASE = 0x0, - hChSys_OPT_ANNOUNCE_JOIN = 0x1, - hChSys_OPT_MSG_DELAY = 0x2, -}; - -enum hChSysChType { - hChSys_PUBLIC = 0, - hChSys_PRIVATE = 1, - hChSys_MAP = 2, - hChSys_ALLY = 3, - hChSys_IRC = 4, -}; - enum CASH_SHOP_TABS { CASHSHOP_TAB_NEW = 0, CASHSHOP_TAB_POPULAR = 1, @@ -518,38 +504,6 @@ struct s_packet_db { short pos[MAX_PACKET_POS]; }; -struct hChSysConfig { - unsigned int *colors; - char **colors_name; - unsigned char colors_count; - bool local, ally, irc; - bool local_autojoin, ally_autojoin; - char local_name[HCHSYS_NAME_LENGTH], ally_name[HCHSYS_NAME_LENGTH], irc_name[HCHSYS_NAME_LENGTH]; - unsigned char local_color, ally_color, irc_color; - bool closing; - bool allow_user_channel_creation; - char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30]; - unsigned short irc_server_port; - bool irc_use_ghost; -}; - -struct hChSysBanEntry { - char name[NAME_LENGTH]; -}; - -struct hChSysCh { - char name[HCHSYS_NAME_LENGTH]; - char pass[HCHSYS_NAME_LENGTH]; - unsigned char color; - DBMap *users; - DBMap *banned; - unsigned int opt; - unsigned int owner; - enum hChSysChType type; - uint16 m; - unsigned char msg_delay; -}; - struct hCSData { unsigned short id; unsigned int price; @@ -576,8 +530,6 @@ struct clif_interface { uint16 map_port; char map_ip_str[128]; int map_fd; - DBMap* channel_db; - struct hChSysConfig *hChSys; /* for clif_clearunit_delayed */ struct eri *delay_clearunit_ers; /* Cash Shop [Ind/Hercules] */ @@ -1065,20 +1017,10 @@ struct clif_interface { void (*user_count) (struct map_session_data* sd, int count); void (*noask_sub) (struct map_session_data *src, struct map_session_data *target, int type); void (*bc_ready) (void); - int (*undisguise_timer) (int tid, int64 tick, int id, intptr_t data); /* Hercules Channel System */ - void (*chsys_create) (struct hChSysCh *channel, char *name, char *pass, unsigned char color); - void (*chsys_msg) (struct hChSysCh *channel, struct map_session_data *sd, char *msg); - void (*chsys_msg2) (struct hChSysCh *channel, char *msg); - void (*chsys_send) (struct hChSysCh *channel, struct map_session_data *sd, const char *msg); - void (*chsys_join) (struct hChSysCh *channel, struct map_session_data *sd); - void (*chsys_left) (struct hChSysCh *channel, struct map_session_data *sd); - void (*chsys_delete) (struct hChSysCh *channel); - void (*chsys_mjoin) (struct map_session_data *sd); - void (*chsys_quit) (struct map_session_data *sd); - void (*chsys_quitg) (struct map_session_data *sd); - void (*chsys_gjoin) (struct guild *g1,struct guild *g2); - void (*chsys_gleave) (struct guild *g1,struct guild *g2); + void (*channel_msg) (struct channel_data *chan, struct map_session_data *sd, char *msg); + void (*channel_msg2) (struct channel_data *chan, char *msg); + int (*undisguise_timer) (int tid, int64 tick, int id, intptr_t data); /* Bank System [Yommy/Hercules] */ void (*bank_deposit) (struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason); void (*bank_withdraw) (struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason); @@ -1132,7 +1074,6 @@ struct clif_interface { void (*pKickFromChat) (int fd,struct map_session_data *sd); void (*pChatLeave) (int fd, struct map_session_data* sd); void (*pTradeRequest) (int fd,struct map_session_data *sd); - void (*chann_config_read) (void); void (*pTradeAck) (int fd,struct map_session_data *sd); void (*pTradeAddItem) (int fd,struct map_session_data *sd); void (*pTradeOk) (int fd,struct map_session_data *sd); diff --git a/src/map/guild.c b/src/map/guild.c index 913bd0e4a..7f116bae1 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -12,6 +12,7 @@ #include <string.h> #include "battle.h" +#include "channel.h" #include "clif.h" #include "instance.h" #include "intif.h" @@ -458,7 +459,7 @@ int guild_recv_info(struct guild *sg) { DBData data; struct map_session_data *sd; bool guild_new = false; - struct hChSysCh *aChSysSave = NULL; + struct channel_data *aChSysSave = NULL; short *instance_save = NULL; unsigned short instances_save = 0; @@ -470,15 +471,9 @@ int guild_recv_info(struct guild *sg) { g->instance = NULL; g->instances = 0; idb_put(guild->db,sg->guild_id,g); - if (clif->hChSys->ally) { - struct hChSysCh *channel; - - CREATE(channel, struct hChSysCh , 1); - safestrncpy(channel->name, clif->hChSys->ally_name, HCHSYS_NAME_LENGTH); - channel->type = hChSys_ALLY; - - clif->chsys_create(channel, NULL, NULL, clif->hChSys->ally_color); - if (clif->hChSys->ally_autojoin) { + if (channel->config->ally) { + struct channel_data *chan = channel->create(HCS_TYPE_ALLY, channel->config->ally_name, channel->config->ally_color); + if (channel->config->ally_autojoin) { struct s_mapiterator* iter = mapit_getallusers(); struct guild *tg[MAX_GUILDALLIANCE]; @@ -494,13 +489,13 @@ int guild_recv_info(struct guild *sg) { if (sd->status.guild_id == sg->guild_id) { // Guild member - clif->chsys_join(channel,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))) - clif->chsys_join(tg[i]->channel, sd); + channel->join_sub(tg[i]->channel, sd, false); } continue; } @@ -508,8 +503,8 @@ int guild_recv_info(struct guild *sg) { for (i = 0; i < MAX_GUILDALLIANCE; i++) { if (tg[i] && sd->status.guild_id == tg[i]->guild_id) { // Shortcut to skip the alliance checks again // Alliance member - if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id))) - clif->chsys_join(channel, sd); + if( !(chan->banned && idb_exists(chan->banned, sd->status.account_id))) + channel->join_sub(chan, sd, false); } } } @@ -518,7 +513,7 @@ int guild_recv_info(struct guild *sg) { } - aChSysSave = channel; + aChSysSave = chan; } before=*sg; @@ -745,18 +740,8 @@ void guild_member_joined(struct map_session_data *sd) g->member[i].sd = sd; sd->guild = g; - if (clif->hChSys->ally && clif->hChSys->ally_autojoin) { - struct hChSysCh *channel = g->channel; - - if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id) ) ) - clif->chsys_join(channel,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))) - clif->chsys_join(sg->channel,sd); - } - } + if (channel->config->ally && channel->config->ally_autojoin) { + channel->join(g->channel, sd, NULL, true); } } @@ -913,8 +898,8 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c if (sd->state.storage_flag == 2) //Close the guild storage. gstorage->close(sd); guild->send_dot_remove(sd); - if (clif->hChSys->ally) { - clif->chsys_quitg(sd); + if (channel->config->ally) { + channel->quit_guild(sd); } sd->status.guild_id = 0; sd->guild = NULL; @@ -1646,12 +1631,15 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id return 0; } - if (g[0] && g[1] && clif->hChSys->ally && ( flag & 1 ) == 0) { + if (g[0] && g[1] && channel->config->ally && ( flag & 1 ) == 0) { if( !(flag & 0x08) ) { - if (clif->hChSys->ally_autojoin) - clif->chsys_gjoin(g[0],g[1]); + if (channel->config->ally_autojoin) { + channel->guild_join_alliance(g[0],g[1]); + channel->guild_join_alliance(g[1],g[0]); + } } else { - clif->chsys_gleave(g[0],g[1]); + channel->guild_leave_alliance(g[0],g[1]); + channel->guild_leave_alliance(g[1],g[0]); } } @@ -1779,9 +1767,9 @@ int guild_broken(int guild_id,int flag) guild->db->foreach(guild->db,guild->broken_sub,guild_id); guild->castle_db->foreach(guild->castle_db,guild->castle_broken_sub,guild_id); gstorage->delete(guild_id); - if (clif->hChSys->ally) { + if (channel->config->ally) { if( g->channel != NULL ) { - clif->chsys_delete(g->channel); + channel->delete(g->channel); } } if( g->instance ) @@ -2280,7 +2268,7 @@ void do_final_guild(void) { for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) { if( g->channel != NULL ) - clif->chsys_delete(g->channel); + channel->delete(g->channel); if( g->instance != NULL ) { aFree(g->instance); g->instance = NULL; diff --git a/src/map/instance.c b/src/map/instance.c index a2d363fc9..dd5709452 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -13,6 +13,7 @@ #include <time.h> #include "../config/core.h" // CELL_NOSTACK +#include "channel.h" #include "clif.h" #include "map.h" #include "npc.h" @@ -483,7 +484,7 @@ void instance_del_map(int16 m) { ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map->list[m].name, instance->list[map->list[m].instance_id].name, m); if( map->list[m].channel ) - clif->chsys_delete(map->list[m].channel); + channel->delete(map->list[m].channel); map->removemapdb(&map->list[m]); memset(&map->list[m], 0x00, sizeof(map->list[0])); diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index 36c19ccbd..d492ad9ca 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -10,7 +10,7 @@ #include <stdlib.h> #include <string.h> -#include "clif.h" +#include "channel.h" #include "map.h" #include "pc.h" #include "../common/cbasetypes.h" @@ -41,7 +41,7 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) { ircbot->last_try = timer->gettick(); - if ((ircbot->fd = make_connection(ircbot->ip, clif->hChSys->irc_server_port, &opt)) > 0) { + if ((ircbot->fd = make_connection(ircbot->ip, channel->config->irc_server_port, &opt)) > 0) { session[ircbot->fd]->func_parse = ircbot->parse; session[ircbot->fd]->flag.server = 1; timer->add(timer->gettick() + 3000, ircbot->identify_timer, 0, 0); @@ -60,7 +60,7 @@ int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) { sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rnd()%777); ircbot->send(send_string); - sprintf(send_string, "NICK %s", clif->hChSys->irc_nick); + sprintf(send_string, "NICK %s", channel->config->irc_nick); ircbot->send(send_string); timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0); @@ -76,15 +76,15 @@ int irc_join_timer(int tid, int64 tick, int id, intptr_t data) { if( !ircbot->isOn ) return 0; - if (clif->hChSys->irc_nick_pw[0] != '\0') { - sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", clif->hChSys->irc_nick_pw); + if (channel->config->irc_nick_pw[0] != '\0') { + sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", channel->config->irc_nick_pw); ircbot->send(send_string); - if (clif->hChSys->irc_use_ghost) { - sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", clif->hChSys->irc_nick, clif->hChSys->irc_nick_pw); + if (channel->config->irc_use_ghost) { + sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", channel->config->irc_nick, channel->config->irc_nick_pw); } } - sprintf(send_string, "JOIN %s", clif->hChSys->irc_channel); + sprintf(send_string, "JOIN %s", channel->config->irc_channel); ircbot->send(send_string); ircbot->isIn = true; @@ -120,7 +120,7 @@ int irc_parse(int fd) { ircbot->isOn = false; ircbot->isIn = false; ircbot->fails = 0; - ircbot->ip = host2ip(clif->hChSys->irc_server); + ircbot->ip = host2ip(channel->config->irc_server); timer->add(timer->gettick() + 120000, ircbot->connect_timer, 0, 0); return 0; } @@ -243,7 +243,7 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg) if( strcmpi(cmd,"ACTION") == 0 ) { if( ircbot->channel ) { snprintf(send_string, 150, "[ #%s ] * IRC.%s %s *",ircbot->channel->name,source_nick,msg); - clif->chsys_msg2(ircbot->channel,send_string); + clif->channel_msg2(ircbot->channel,send_string); } } else if( strcmpi(cmd,"ERRMSG") == 0 ) { // Ignore it @@ -290,10 +290,10 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) { irc_privmsg_ctcp(fd, command, source, target, message); #ifdef IRCBOT_DEBUG - } else if (strcmpi(target, clif->hChSys->irc_nick) == 0) { + } else if (strcmpi(target, channel->config->irc_nick) == 0) { ShowDebug("irc_privmsg: Received message from %s: '%s'\n", source ? source : "(null)", msg); #endif // IRCBOT_DEBUG - } else if (msg && strcmpi(target, clif->hChSys->irc_channel) == 0) { + } else if (msg && strcmpi(target, channel->config->irc_channel) == 0) { char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH]; source_nick[0] = source_ident[0] = source_host[0] = '\0'; @@ -305,7 +305,7 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) { size_t padding_len = strlen(ircbot->channel->name) + strlen(source_nick) + 13; while (1) { snprintf(send_string, 150, "[ #%s ] IRC.%s : %s",ircbot->channel->name,source_nick,msg); - clif->chsys_msg2(ircbot->channel,send_string); + clif->channel_msg2(ircbot->channel,send_string); //break; // Uncomment this line to truncate long messages instead of posting them as multiple lines if (strlen(msg) <= 149 - padding_len) break; @@ -330,7 +330,7 @@ void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) { if( ircbot->channel ) { snprintf(send_string, 150, "[ #%s ] User IRC.%s joined the channel.",ircbot->channel->name,source_nick); - clif->chsys_msg2(ircbot->channel,send_string); + clif->channel_msg2(ircbot->channel,send_string); } } @@ -352,7 +352,7 @@ void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) { snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [Quit: %s]",ircbot->channel->name,source_nick,msg); else snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [%s]",ircbot->channel->name,source_nick,msg); - clif->chsys_msg2(ircbot->channel,send_string); + clif->channel_msg2(ircbot->channel,send_string); } } @@ -371,7 +371,7 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) { if( ircbot->channel ) { snprintf(send_string, 150, "[ #%s ] User IRC.%s is now known as IRC.%s",ircbot->channel->name,source_nick,msg); - clif->chsys_msg2(ircbot->channel,send_string); + clif->channel_msg2(ircbot->channel,send_string); } } @@ -380,10 +380,16 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) { * @param name Sender's name * @param msg Message text */ -void irc_relay(char *name, const char *msg) { - if( !ircbot->isIn ) +void irc_relay(const char *name, const char *msg) +{ + if (!ircbot->isIn) return; - sprintf(send_string,"PRIVMSG %s :[ %s ] : %s", clif->hChSys->irc_channel, name, msg); + + if (name) + sprintf(send_string,"PRIVMSG %s :[ %s ] : %s", channel->config->irc_channel, name, msg); + else + sprintf(send_string,"PRIVMSG %s :%s", channel->config->irc_channel, msg); + ircbot->send(send_string); } @@ -406,12 +412,12 @@ void irc_bot_init(bool minimal) { if (minimal) return; - if (!clif->hChSys->irc) + if (!channel->config->irc) return; - if (!(ircbot->ip = host2ip(clif->hChSys->irc_server))) { - ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", clif->hChSys->irc_server); - clif->hChSys->irc = false; + if (!(ircbot->ip = host2ip(channel->config->irc_server))) { + ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", channel->config->irc_server); + channel->config->irc = false; return; } @@ -444,7 +450,7 @@ void irc_bot_init(bool minimal) { void irc_bot_final(void) { int i; - if (!clif->hChSys->irc) + if (!channel->config->irc) return; if( ircbot->isOn ) { ircbot->send("QUIT :Hercules is shutting down"); diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h index 23c2fabc8..8dcfea5bd 100644 --- a/src/map/irc-bot.h +++ b/src/map/irc-bot.h @@ -14,7 +14,7 @@ #define IRC_FUNC_LENGTH 30 #define IRC_MESSAGE_LENGTH 500 -struct hChSysCh; +struct channel_data; struct irc_func { char name[IRC_FUNC_LENGTH]; @@ -29,7 +29,7 @@ struct irc_bot_interface { uint32 ip; unsigned short port; /* */ - struct hChSysCh *channel; + struct channel_data *channel; /* */ struct { struct irc_func **list; @@ -50,7 +50,7 @@ struct irc_bot_interface { int (*join_timer) (int tid, int64 tick, int id, intptr_t data); /* */ void (*send)(char *str); - void (*relay) (char *name, const char *msg); + void (*relay) (const char *name, const char *msg); /* */ void (*pong) (int fd, char *cmd, char *source, char *target, char *msg); void (*privmsg) (int fd, char *cmd, char *source, char *target, char *msg); diff --git a/src/map/map.c b/src/map/map.c index ae31f01ec..1f893269b 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -17,6 +17,7 @@ #include "atcommand.h" #include "battle.h" #include "battleground.h" +#include "channel.h" #include "chat.h" #include "chrif.h" #include "clif.h" @@ -1799,7 +1800,7 @@ int map_quit(struct map_session_data *sd) { if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */ bg->team_leave(sd,BGTL_QUIT); - if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !clif->hChSys->closing) + if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !channel->config->closing) pc->autotrade_update(sd,PAUC_REMOVE); skill->cooldown_save(sd); @@ -1856,11 +1857,7 @@ int map_quit(struct map_session_data *sd) { unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK); } - if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) { - clif->chsys_left(map->list[sd->bl.m].channel,sd); - } - - clif->chsys_quit(sd); + channel->quit(sd); unit->remove_map_pc(sd,CLR_RESPAWN); @@ -3189,7 +3186,7 @@ void map_clean(int i) { } if( map->list[i].channel ) - clif->chsys_delete(map->list[i].channel); + channel->delete(map->list[i].channel); } void do_final_maps(void) { int i, v = 0; @@ -3248,7 +3245,7 @@ void do_final_maps(void) { aFree(map->list[i].drop_list); if( map->list[i].channel ) - clif->chsys_delete(map->list[i].channel); + channel->delete(map->list[i].channel); if( map->list[i].qi_data ) aFree(map->list[i].qi_data); @@ -5356,7 +5353,7 @@ int do_final(void) { ShowStatus("Terminating...\n"); - clif->hChSys->closing = true; + channel->config->closing = true; HPM->event(HPET_FINAL); if (map->cpsd) aFree(map->cpsd); @@ -5392,8 +5389,9 @@ int do_final(void) { atcommand->final(); battle->final(); + ircbot->final();/* before channel. */ + channel->final(); chrif->final(); - ircbot->final();/* before clif. */ clif->final(); npc->final(); quest->final(); @@ -5579,6 +5577,7 @@ void map_hp_symbols(void) { HPM->share(battle,"battle"); HPM->share(bg,"battlegrounds"); HPM->share(buyingstore,"buyingstore"); + HPM->share(channel,"channel"); HPM->share(clif,"clif"); HPM->share(chrif,"chrif"); HPM->share(guild,"guild"); @@ -5634,6 +5633,7 @@ void map_load_defaults(void) { battle_defaults(); battleground_defaults(); buyingstore_defaults(); + channel_defaults(); clif_defaults(); chrif_defaults(); guild_defaults(); @@ -5940,6 +5940,7 @@ int do_init(int argc, char *argv[]) atcommand->init(minimal); battle->init(minimal); instance->init(minimal); + channel->init(minimal); chrif->init(minimal); clif->init(minimal); ircbot->init(minimal); diff --git a/src/map/map.h b/src/map/map.h index c28a65f52..9fca3e606 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -19,7 +19,7 @@ struct mob_data; struct npc_data; -struct hChSysCh; +struct channel_data; enum E_MAPSERVER_ST { MAPSERVER_ST_RUNNING = CORE_ST_LAST, @@ -694,7 +694,7 @@ struct map_data { struct map_zone_data *prev_zone; /* Hercules Local Chat */ - struct hChSysCh *channel; + struct channel_data *channel; /* invincible_time_inc mapflag */ unsigned int invincible_time_inc; diff --git a/src/map/pc.c b/src/map/pc.c index 806bfb42c..2013bb652 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -15,6 +15,7 @@ #include "atcommand.h" // get_atcommand_level() #include "battle.h" // battle_config #include "battleground.h" +#include "channel.h" #include "chat.h" #include "chrif.h" #include "clif.h" @@ -5042,8 +5043,8 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int vending->close(sd); } - if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) { - clif->chsys_left(map->list[sd->bl.m].channel,sd); + if (map->list[sd->bl.m].channel) { + channel->leave(map->list[sd->bl.m].channel,sd); } } diff --git a/src/map/pc.h b/src/map/pc.h index 1785bd4c4..f6b6329b4 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -491,10 +491,9 @@ struct map_session_data { int shadowform_id; /* [Ind/Hercules] */ - struct hChSysCh **channels; + struct channel_data **channels; unsigned char channel_count; - struct hChSysCh *gcbind; - bool stealth; + struct channel_data *gcbind; unsigned char fontcolor; unsigned int fontcolor_tid; int64 hchsysch_tick; diff --git a/src/map/script.c b/src/map/script.c index a2ea86ac6..f50e56d2d 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -16,6 +16,7 @@ #include "atcommand.h" #include "battle.h" #include "battleground.h" +#include "channel.h" #include "chat.h" #include "chrif.h" #include "clif.h" @@ -19012,6 +19013,29 @@ BUILDIN(shopcount) { return true; } +/** + * @call channelmes("#channel", "message"); + * + * Sends a message through the specified chat channel. + * + */ +BUILDIN(channelmes) +{ + struct map_session_data *sd = script->rid2sd(st); + const char *channelname = script_getstr(st, 2); + struct channel_data *chan = channel->search(channelname, sd); + + if (!chan) { + script_pushint(st, 0); + return true; + } + + channel->send(chan, NULL, script_getstr(st, 3)); + + script_pushint(st, 1); + return true; +} + // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT BUILDIN(defpattern); @@ -19637,6 +19661,8 @@ void script_parse_builtin(void) { BUILDIN_DEF(tradertype,"i"), BUILDIN_DEF(purchaseok,""), BUILDIN_DEF(shopcount, "i"), + + BUILDIN_DEF(channelmes, "ss"), }; int i, len = ARRAYLENGTH(BUILDIN); RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up |