Index: src/map/clif.c =================================================================== --- src/map/clif.c (revision 17265) +++ src/map/clif.c (working copy) @@ -44,6 +44,7 @@ #include "mail.h" #include "quest.h" #include "cashshop.h" +#include "channel.h" #include #include @@ -53,8 +54,6 @@ /* for clif_clearunit_delayed */ static struct eri *delay_clearunit_ers; -static DBMap* channel_db; // channels -DBMap* clif_get_channel_db(void){ return channel_db; } //#define DUMP_UNKNOWN_PACKET //#define DUMP_INVALID_PACKET @@ -5490,52 +5489,11 @@ aFree(buf); } -/*========================================== - * Channel System - *------------------------------------------*/ -void clif_chsys_create(struct raChSysCh *channel, char *name, char *pass, unsigned char color) { - channel->users = idb_alloc(DB_OPT_BASE); - if( name ) - safestrncpy(channel->name, name, RACHSYS_NAME_LENGTH); - channel->color = color; - if( !pass ) - channel->pass[0] = '\0'; - else - safestrncpy(channel->pass, pass, RACHSYS_NAME_LENGTH); - - channel->opt = raChSys_OPT_BASE; - - if( channel->type != raChSys_MAP && channel->type != raChSys_ALLY ) - strdb_put(channel_db, channel->name, channel); -} - -void clif_chsys_join(struct raChSysCh *channel, struct map_session_data *sd) { - RECREATE(sd->channels, struct raChSysCh *, ++sd->channel_count); - sd->channels[ sd->channel_count - 1 ] = channel; - idb_put(channel->users, sd->status.char_id, sd); - - if( sd->stealth ) { - sd->stealth = false; - } else if( channel->opt & raChSys_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); - } -} - -void clif_chsys_send(struct raChSysCh *channel, struct map_session_data *sd, char *msg) { - char message[150]; - snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg); - clif_chsys_msg(channel,sd,message); -} - +/* + * Display *msg from *sd to all *user in channel + */ void clif_chsys_msg(struct raChSysCh *channel, struct map_session_data *sd, char *msg) { - DBIterator *iter = db_iterator(channel->users); + DBIterator *iter; struct map_session_data *user; unsigned short msg_len = strlen(msg) + 1; @@ -5546,6 +5504,7 @@ WFIFOL(sd->fd,8) = raChSys.colors[channel->color]; safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); + iter = db_iterator(channel->users); for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) { if( user->fd == sd->fd ) continue; @@ -5559,225 +5518,6 @@ dbi_destroy(iter); } -void clif_chsys_mjoin(struct map_session_data *sd) { - if( !map[sd->bl.m].channel ) { - CREATE(map[sd->bl.m].channel, struct raChSysCh , 1); - safestrncpy(map[sd->bl.m].channel->name, raChSys.local_name, RACHSYS_NAME_LENGTH); - map[sd->bl.m].channel->type = raChSys_MAP; - map[sd->bl.m].channel->m = sd->bl.m; - - clif_chsys_create(map[sd->bl.m].channel,NULL,NULL,raChSys.local_color); - } - clif_chsys_join(map[sd->bl.m].channel,sd); - - if( !( map[sd->bl.m].channel->opt & raChSys_OPT_ANNOUNCE_JOIN ) ) { - char mout[60]; - sprintf(mout, msg_txt(sd,1435),raChSys.local_name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'. - clif_disp_onlyself(sd, mout, strlen(mout)); - } -} - -void clif_chsys_left(struct raChSysCh *channel, struct map_session_data *sd) { - unsigned char i; - idb_remove(channel->users,sd->status.char_id); - - if( channel == sd->gcbind ) - sd->gcbind = NULL; - - if( !db_size(channel->users) && channel->type == raChSys_PRIVATE ) { - clif_chsys_delete(channel); - } else if( !raChSys.closing && (channel->opt & raChSys_OPT_ANNOUNCE_JOIN) ) { - char message[60]; - sprintf(message, "#%s '%s' left",channel->name,sd->status.name); - clif_chsys_msg(channel,sd,message); - } - - ARR_FIND(0, sd->channel_count, i, sd->channels[i] == channel); - if( i < sd->channel_count ) { - unsigned char cursor = 0; - sd->channels[i] = NULL; - 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_chsys_delete(struct raChSysCh *channel) { - if( db_size(channel->users) && !raChSys.closing ) { - struct map_session_data *sd; - unsigned char i; - DBIterator *iter = db_iterator(channel->users); - for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { //for all users - ARR_FIND(0, sd->channel_count, i, sd->channels[i] == channel); //found cur chan - if( i < sd->channel_count ) { - unsigned char cursor = 0; - sd->channels[i] = NULL; - for( i = 0; i < sd->channel_count; i++ ) { //move down links - if( sd->channels[i] == NULL ) - continue; - if( cursor != i ) - sd->channels[cursor] = sd->channels[i]; - cursor++; - } - if ( !(sd->channel_count = cursor) ) { //news chan count = total - aFree(sd->channels); - sd->channels = NULL; - } - } - } - dbi_destroy(iter); - } - db_destroy(channel->users); - if( channel->m ) { - map[channel->m].channel = NULL; - aFree(channel); - } else if ( channel->type == raChSys_ALLY ) - aFree(channel); - else if( !raChSys.closing ) - strdb_remove(channel_db, channel->name); -} - -void clif_read_channels_config(void) { - config_t channels_conf; - config_setting_t *chsys = NULL; - const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name - - if (conf_read_file(&channels_conf, config_filename)) - return; - - chsys = config_lookup(&channels_conf, "chsys"); - - if (chsys != NULL) { - config_setting_t *settings = config_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; - int ally_enabled = 0, local_enabled = 0, - local_autojoin = 0, ally_autojoin = 0, - allow_user_channel_creation = 0; - - if( !config_setting_lookup_string(settings, "map_local_channel_name", &local_name) ) - local_name = "map"; - safestrncpy(raChSys.local_name, local_name, RACHSYS_NAME_LENGTH); - - if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_name) ) - ally_name = "ally"; - safestrncpy(raChSys.ally_name, ally_name, RACHSYS_NAME_LENGTH); - - config_setting_lookup_bool(settings, "map_local_channel", &local_enabled); - config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); - - if( local_enabled ) - raChSys.local = true; - if( ally_enabled ) - raChSys.ally = true; - - config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); - config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); - - if( local_autojoin ) - raChSys.local_autojoin = true; - if( ally_autojoin ) - raChSys.ally_autojoin = true; - - config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); - - if( allow_user_channel_creation ) - raChSys.allow_user_channel_creation = true; - - if( (colors = config_setting_get_member(settings, "colors")) != NULL ) { - int color_count = config_setting_length(colors); - CREATE( raChSys.colors, unsigned long, color_count ); - CREATE( raChSys.colors_name, char *, color_count ); - for(i = 0; i < color_count; i++) { - config_setting_t *color = config_setting_get_elem(colors, i); - - CREATE( raChSys.colors_name[i], char, RACHSYS_NAME_LENGTH ); - - safestrncpy(raChSys.colors_name[i], config_setting_name(color), RACHSYS_NAME_LENGTH); - - raChSys.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0); - raChSys.colors[i] = (raChSys.colors[i] & 0x0000FF) << 16 | (raChSys.colors[i] & 0x00FF00) | (raChSys.colors[i] & 0xFF0000) >> 16;//RGB to BGR - } - raChSys.colors_count = color_count; - } - - config_setting_lookup_string(settings, "map_local_channel_color", &local_color); - - for (k = 0; k < raChSys.colors_count; k++) { - if( strcmpi(raChSys.colors_name[k],local_color) == 0 ) - break; - } - - if( k < raChSys.colors_count ) { - raChSys.local_color = k; - } else { - ShowError("channels.conf: unknown color '%s' for channel 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); - raChSys.local = false; - } - - config_setting_lookup_string(settings, "ally_channel_color", &ally_color); - - for (k = 0; k < raChSys.colors_count; k++) { - if( strcmpi(raChSys.colors_name[k],ally_color) == 0 ) - break; - } - - if( k < raChSys.colors_count ) { - raChSys.ally_color = k; - } else { - ShowError("channels.conf: unknown color '%s' for channel 'ally_channel_color', disabling '#%s'...\n",local_color,ally_name); - raChSys.ally = false; - } - - if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) { - int channel_count = config_setting_length(channels); - - for(i = 0; i < channel_count; i++) { - config_setting_t *channel = config_setting_get_elem(channels, i); - const char *name = config_setting_name(channel); - const char *color = config_setting_get_string_elem(channels,i); - struct raChSysCh *chd; - - for (k = 0; k < raChSys.colors_count; k++) { - if( strcmpi(raChSys.colors_name[k],color) == 0 ) - break; - } - if( k == raChSys.colors_count ) { - ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); - continue; - } - if( strcmpi(name,raChSys.local_name) == 0 || strcmpi(name,raChSys.ally_name) == 0 || strdb_exists(channel_db, name) ) { - ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); - continue; - - } - CREATE( chd, struct raChSysCh, 1 ); - - safestrncpy(chd->name, name, RACHSYS_NAME_LENGTH); - chd->type = raChSys_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(channel_db), config_filename); - config_destroy(&channels_conf); - } -} - - /// Displays heal effect (ZC_RECOVERY). /// 013d .W .W /// var id: @@ -9565,7 +9305,7 @@ sd->state.changemap = false; if( raChSys.local && raChSys.local_autojoin && !map[sd->bl.m].flag.chsysnolocalaj ) { - clif_chsys_mjoin(sd); + channel_mjoin(sd); } } @@ -9867,7 +9607,7 @@ } 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]; @@ -10258,12 +9998,13 @@ } else if( target[0] == '#' ) { struct raChSysCh *channel = NULL; char* chname = target; + DBMap* channel_db = channel_get_db(); chname++; if( raChSys.local && strcmpi(chname, raChSys.local_name) == 0 ) { if( !map[sd->bl.m].channel ) { - clif_chsys_mjoin(sd); + channel_mjoin(sd); } channel = map[sd->bl.m].channel; } else if( raChSys.ally && sd->status.guild_id && strcmpi(chname, raChSys.ally_name) == 0 ) { @@ -10275,10 +10016,10 @@ unsigned char k; ARR_FIND(0, sd->channel_count, k, sd->channels[k] == channel); if( k < sd->channel_count ) { - clif_chsys_send(channel,sd,message); + channel_send(channel,sd,message); } else if( channel->pass[0] == '\0' ) { - clif_chsys_join(channel,sd); - clif_chsys_send(channel,sd,message); + channel_join(channel,sd); + channel_send(channel,sd,message); } else { clif_displaymessage(fd, msg_txt(sd,1402)); //You're not in that channel, type '@join <#channel_name>' } @@ -17374,34 +17115,9 @@ add_timer_func_list(clif_delayquit, "clif_delayquit"); delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); - - channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, RACHSYS_NAME_LENGTH); - raChSys.ally = raChSys.local = raChSys.ally_autojoin = raChSys.local_autojoin = false; - clif_read_channels_config(); - return 0; } void do_final_clif(void) { - DBIterator *iter = db_iterator(channel_db); - struct raChSysCh *channel; - 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 < raChSys.colors_count; i++) { - aFree(raChSys.colors_name[i]); - } - - if( raChSys.colors_count ) { - aFree(raChSys.colors_name); - aFree(raChSys.colors); - } - - db_destroy(channel_db); ers_destroy(delay_clearunit_ers); } Index: src/map/clif.h =================================================================== --- src/map/clif.h (revision 17265) +++ src/map/clif.h (working copy) @@ -6,7 +6,9 @@ #include "../common/cbasetypes.h" #include "../common/db.h" //dbmap + //#include "../common/mmo.h" +struct raChSysCh; struct item; struct storage_data; struct guild_storage; @@ -775,55 +777,7 @@ unsigned long color_table[COLOR_MAX]; int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg); -/** - * Channel System - **/ -#define RACHSYS_NAME_LENGTH 20 - -enum raChSysChOpt { - raChSys_OPT_BASE = 0, - raChSys_OPT_ANNOUNCE_JOIN = 1, -}; - -enum raChSysChType { - raChSys_PUBLIC = 0, - raChSys_PRIVATE = 1, - raChSys_MAP = 2, - raChSys_ALLY = 3, -}; - -struct { - unsigned long *colors; - char **colors_name; - unsigned char colors_count; - bool local, ally; - bool local_autojoin, ally_autojoin; - char local_name[RACHSYS_NAME_LENGTH], ally_name[RACHSYS_NAME_LENGTH]; - unsigned char local_color, ally_color; - bool closing; - bool allow_user_channel_creation; -} raChSys; - -struct raChSysCh { - char name[RACHSYS_NAME_LENGTH]; - char pass[RACHSYS_NAME_LENGTH]; - unsigned char color; - DBMap *users; - unsigned int opt; - unsigned int owner; - enum raChSysChType type; - uint16 m; -}; - -struct DBMap* clif_get_channel_db(void); -void clif_chsys_create(struct raChSysCh *channel, char *name, char *pass, unsigned char color); void clif_chsys_msg(struct raChSysCh *channel, struct map_session_data *sd, char *msg); -void clif_chsys_send(struct raChSysCh *channel, struct map_session_data *sd, char *msg); -void clif_chsys_join(struct raChSysCh *channel, struct map_session_data *sd); -void clif_chsys_left(struct raChSysCh *channel, struct map_session_data *sd); -void clif_chsys_delete(struct raChSysCh *channel); -void clif_chsys_mjoin(struct map_session_data *sd); -void clif_read_channels_config(void); #define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0; Index: src/map/guild.c =================================================================== --- src/map/guild.c (revision 17265) +++ src/map/guild.c (working copy) @@ -21,6 +21,7 @@ #include "mob.h" #include "intif.h" #include "clif.h" +#include "channel.h" #include "skill.h" #include "log.h" @@ -514,21 +515,21 @@ safestrncpy(channel->name, raChSys.ally_name, RACHSYS_NAME_LENGTH); channel->type = raChSys_ALLY; - clif_chsys_create(channel,NULL,NULL,raChSys.ally_color); + channel_create(channel,NULL,NULL,raChSys.ally_color); if( raChSys.ally_autojoin ) { struct s_mapiterator* iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { if( sd->status.guild_id ) { if( sd->status.guild_id == sg->guild_id ) { - clif_chsys_join(channel,sd); + channel_join(channel,sd); sd->guild = g; continue; } for (i = 0; i < MAX_GUILDALLIANCE; i++) { if( sg->alliance[i].guild_id == sd->status.guild_id ) { - clif_chsys_join(channel,sd); + channel_join(channel,sd); break; } } @@ -757,11 +758,11 @@ if( raChSys.ally && raChSys.ally_autojoin ) { struct guild* sg = NULL; - clif_chsys_join((struct raChSysCh*)g->channel,sd); + channel_join((struct raChSysCh*)g->channel,sd); for (i = 0; i < MAX_GUILDALLIANCE; i++) { if( g->alliance[i].guild_id && (sg = guild_search(g->alliance[i].guild_id) ) ) { - clif_chsys_join((struct raChSysCh*)sg->channel,sd); + channel_join((struct raChSysCh*)sg->channel,sd); break; } } @@ -913,7 +914,7 @@ uint8 ch_count = sd->channel_count; for (i = 0; i < ch_count; i++) { if( sd->channels[i] && sd->channels[i]->type == raChSys_ALLY ) - clif_chsys_left(sd->channels[i],sd); + channel_left(sd->channels[i],sd); } } sd->status.guild_id = 0; @@ -1753,7 +1754,7 @@ guild_storage_delete(guild_id); if( raChSys.ally ) { if( g->channel != NULL ) { - clif_chsys_delete(( struct raChSysCh * )g->channel); + channel_delete(( struct raChSysCh * )g->channel); } } idb_remove(guild_db,guild_id); @@ -2204,7 +2205,7 @@ for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) { if( g->channel != NULL ) - clif_chsys_delete((struct raChSysCh *)g->channel); + channel_delete((struct raChSysCh *)g->channel); } dbi_destroy(iter); Index: src/map/pc.c =================================================================== --- src/map/pc.c (revision 17265) +++ src/map/pc.c (working copy) @@ -16,6 +16,7 @@ #include "atcommand.h" // get_atcommand_level() #include "battle.h" // battle_config #include "battleground.h" +#include "channel.h" #include "chrif.h" #include "clif.h" #include "date.h" // is_day_of_*() @@ -4769,7 +4770,7 @@ } if( raChSys.local && map[sd->bl.m].channel && idb_exists(map[sd->bl.m].channel->users, sd->status.char_id) ) { - clif_chsys_left(map[sd->bl.m].channel,sd); + channel_left(map[sd->bl.m].channel,sd); } } Index: src/map/map.c =================================================================== --- src/map/map.c (revision 17265) +++ src/map/map.c (working copy) @@ -48,6 +48,8 @@ #include "log.h" #include "mail.h" #include "cashshop.h" +#include "channel.h" + #include #include #include @@ -3563,7 +3565,7 @@ if (map[i].m >= 0) { map_foreachinmap(cleanup_sub, i, BL_ALL); if( map[i].channel != NULL ) - clif_chsys_delete((struct raChSysCh *)map[i].channel); + channel_delete((struct raChSysCh *)map[i].channel); } } ShowStatus("Cleaned up %d maps."CL_CLL"\n", map_num); @@ -3574,6 +3576,7 @@ do_final_atcommand(); do_final_battle(); + do_final_channel(); do_final_chrif(); do_final_clif(); do_final_npc(); @@ -3876,6 +3879,7 @@ do_init_atcommand(); do_init_battle(); do_init_instance(); + do_init_channel(); do_init_chrif(); do_init_clif(); do_init_script(); Index: src/map/Makefile.in =================================================================== --- src/map/Makefile.in (revision 17265) +++ src/map/Makefile.in (working copy) @@ -17,7 +17,7 @@ storage.o skill.o atcommand.o battle.o battleground.o \ intif.o trade.o party.o vending.o guild.o pet.o \ log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ - buyingstore.o searchstore.o duel.o pc_groups.o elemental.o cashshop.o + buyingstore.o searchstore.o duel.o pc_groups.o elemental.o cashshop.o channel.o MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \ obj_sql/mapreg_sql.o MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ @@ -25,7 +25,7 @@ storage.h skill.h atcommand.h battle.h battleground.h \ intif.h trade.h party.h vending.h guild.h pet.h \ log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \ - buyingstore.h searchstore.h duel.h pc_groups.h elemental.h cashshop.h \ + buyingstore.h searchstore.h duel.h pc_groups.h elemental.h cashshop.h channel.h\ ../config/core.h ../config/renewal.h ../config/secure.h ../config/const.h \ ../config/classes/general.h @@ -91,10 +91,10 @@ # missing object files ../common/obj_all/common.a: @$(MAKE) -C ../common sql - + ../common/obj_sql/common_sql.a: @$(MAKE) -C ../common sql - + MT19937AR_OBJ: @$(MAKE) -C ../../3rdparty/mt19937ar Index: src/map/atcommand.c =================================================================== --- src/map/atcommand.c (revision 17265) +++ src/map/atcommand.c (working copy) @@ -17,6 +17,7 @@ #include "atcommand.h" #include "battle.h" #include "chat.h" +#include "channel.h" #include "clif.h" #include "chrif.h" #include "duel.h" @@ -5626,11 +5627,11 @@ struct guild *g = sd->guild, *sg; if( g ) { if( idb_exists(((struct raChSysCh *)g->channel)->users, sd->status.char_id) ) - clif_chsys_left((struct raChSysCh *)g->channel,sd); + channel_left((struct raChSysCh *)g->channel,sd); for (i = 0; i < MAX_GUILDALLIANCE; i++) { if( g->alliance[i].guild_id && (sg = guild_search(g->alliance[i].guild_id) ) ) { if( idb_exists(((struct raChSysCh *)sg->channel)->users, sd->status.char_id) ) - clif_chsys_left((struct raChSysCh *)sg->channel,sd); + channel_left((struct raChSysCh *)sg->channel,sd); break; } } @@ -5640,7 +5641,7 @@ uint8 count = sd->channel_count; for( i = 0; i < count; i++ ) { if( sd->channels[i] != NULL ) - clif_chsys_left(sd->channels[i],sd); + channel_left(sd->channels[i],sd); } } clif_authfail_fd(sd->fd, 15); @@ -8786,7 +8787,7 @@ { struct raChSysCh *channel; char name[RACHSYS_NAME_LENGTH], pass[RACHSYS_NAME_LENGTH]; - DBMap* channel_db = clif_get_channel_db(); + DBMap* channel_db = channel_get_db(); if( !message || !*message || sscanf(message, "%s %s", name, pass) < 1 ) { sprintf(atcmd_output, msg_txt(sd,1399),command); // Unknown Channel (usage: %s <#channel_name>) @@ -8795,7 +8796,7 @@ } if( raChSys.local && strcmpi(name + 1, raChSys.local_name) == 0 ) { if( !map[sd->bl.m].channel ) { - clif_chsys_mjoin(sd); + channel_mjoin(sd); return 0; } else channel = map[sd->bl.m].channel; @@ -8829,7 +8830,7 @@ clif_displaymessage(fd, atcmd_output); } - clif_chsys_join(channel,sd); + channel_join(channel,sd); return 0; } @@ -8872,7 +8873,7 @@ struct raChSysCh *channel; char key[RACHSYS_NAME_LENGTH], sub1[RACHSYS_NAME_LENGTH], sub2[RACHSYS_NAME_LENGTH], sub3[RACHSYS_NAME_LENGTH]; unsigned char k = 0; - DBMap* channel_db = clif_get_channel_db(); + DBMap* channel_db = channel_get_db(); sub1[0] = sub2[0] = sub3[0] = '\0'; if( !message || !*message || sscanf(message, "%s %s %s %s", key, sub1, sub2, sub3) < 1 ) { @@ -8900,7 +8901,7 @@ CREATE( channel, struct raChSysCh, 1 ); - clif_chsys_create(channel,sub1 + 1,sub2,0); + channel_create(channel,sub1 + 1,sub2,0); channel->owner = sd->status.char_id; channel->type = raChSys_PRIVATE; @@ -8910,7 +8911,7 @@ clif_displaymessage(fd, atcmd_output); } - clif_chsys_join(channel,sd); + channel_join(channel,sd); } else if ( strcmpi(key,"list") == 0 ) { if( sub1[0] != '\0' && strcmpi(sub1,"colors") == 0 ) { @@ -8994,7 +8995,7 @@ clif_displaymessage(fd, atcmd_output); return -1; } - clif_chsys_left(sd->channels[k],sd); + channel_left(sd->channels[k],sd); sprintf(atcmd_output, msg_txt(sd,1426),sub1); // You've left the '%s' channel. clif_displaymessage(fd, atcmd_output); } else if ( strcmpi(key,"bindto") == 0 ) { Index: src/map/channel.c =================================================================== --- src/map/channel.c (revision 0) +++ src/map/channel.c (revision 0) @@ -0,0 +1,336 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/conf.h" //libconfig +#include "../common/showmsg.h" +#include "../common/strlib.h" //safestrncpy +#include "../common/socket.h" //set_eof + +#include "map.h" //msg_conf +#include "clif.h" //clif_chsys_msg +#include "channel.h" + +#include +#include + +static DBMap* channel_db; // channels +DBMap* channel_get_db(void){ return channel_db; } //private or public chat + +/* + * Create *channel + * - then add it in channel_db if type not map or ally + */ +void channel_create(struct raChSysCh *channel, char *name, char *pass, unsigned char color) { + channel->users = idb_alloc(DB_OPT_BASE); + if( name ) + safestrncpy(channel->name, name, RACHSYS_NAME_LENGTH); + channel->color = color; + if( !pass ) + channel->pass[0] = '\0'; + else + safestrncpy(channel->pass, pass, RACHSYS_NAME_LENGTH); + + channel->opt = raChSys_OPT_BASE; + + if( channel->type != raChSys_MAP && channel->type != raChSys_ALLY ) + strdb_put(channel_db, channel->name, channel); +} + +/* + * Delete *channel + * - check if ramin user in channel and make them all quit + * -@TODO add return value + */ +void channel_delete(struct raChSysCh *channel) { + if( db_size(channel->users) && !raChSys.closing ) { + struct map_session_data *sd; + DBIterator *iter = db_iterator(channel->users); + for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { //for all users + channel_left(channel,sd); //make all quit + } + dbi_destroy(iter); + if(channel->type == raChSys_PRIVATE) //when all quit it will call delete @FIXME only the case for private + return; + } + db_destroy(channel->users); + switch(channel->type){ + case raChSys_MAP: + map[channel->m].channel = NULL; + aFree(channel); + break; + case raChSys_ALLY: + aFree(channel); + break; + } + if( !raChSys.closing ) + strdb_remove(channel_db, channel->name); +} + +/* + * Make *sd join *channel + * - add charid to channel user list + * - add *channel to user channel list + * TODO ad check if not exist already, add return values + */ +void channel_join(struct raChSysCh *channel, struct map_session_data *sd) { + RECREATE(sd->channels, struct raChSysCh *, ++sd->channel_count); + sd->channels[ sd->channel_count - 1 ] = channel; + idb_put(channel->users, sd->status.char_id, sd); + + if( sd->stealth ) { + sd->stealth = false; + } else if( channel->opt & raChSys_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); + } +} + +/* + * Make *sd join the map channel + * create the map_channel if not exist + */ +void channel_mjoin(struct map_session_data *sd) { + if( !map[sd->bl.m].channel ) { + CREATE(map[sd->bl.m].channel, struct raChSysCh , 1); + safestrncpy(map[sd->bl.m].channel->name, raChSys.local_name, RACHSYS_NAME_LENGTH); + map[sd->bl.m].channel->type = raChSys_MAP; + map[sd->bl.m].channel->m = sd->bl.m; + + channel_create(map[sd->bl.m].channel,NULL,NULL,raChSys.local_color); + } + channel_join(map[sd->bl.m].channel,sd); + + if( !( map[sd->bl.m].channel->opt & raChSys_OPT_ANNOUNCE_JOIN ) ) { + char mout[60]; + sprintf(mout, msg_txt(sd,1435),raChSys.local_name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'. + clif_disp_onlyself(sd, mout, strlen(mout)); + } +} + +/* + * Make *sd leave *channel and cleanup association. + * if no one remain in chat delete it (PRIVATE only atm) + */ +void channel_left(struct raChSysCh *channel, struct map_session_data *sd) { + unsigned char i; + + if( channel == sd->gcbind ) + sd->gcbind = NULL; + + if( !raChSys.closing && (channel->opt & raChSys_OPT_ANNOUNCE_JOIN) ) { + char message[60]; + sprintf(message, "#%s '%s' left",channel->name,sd->status.name); + clif_chsys_msg(channel,sd,message); + } + + ARR_FIND(0, sd->channel_count, i, sd->channels[i] == channel); + if( i < sd->channel_count ) { + unsigned char cursor = 0; + sd->channels[i] = NULL; + for( i = 0; i < sd->channel_count; i++ ) { //slice move list down + if( sd->channels[i] == NULL ) + continue; + if( cursor != i ) + sd->channels[cursor] = sd->channels[i]; + cursor++; + } + if ( !(sd->channel_count = cursor) ) { //if in no more chan delete db + aFree(sd->channels); + sd->channels = NULL; + } + } + + idb_remove(channel->users,sd->status.char_id); //remove user for channel user list + if( !db_size(channel->users) && channel->type == raChSys_PRIVATE ) + channel_delete(channel); + +} + +/* + * Format *msg from *sd to send it in *channel + * Also truncate extra char if msg too long (max=RACHSYS_MSG_LENGTH) + */ +void channel_send(struct raChSysCh *channel, struct map_session_data *sd, char *msg) { + char message[RACHSYS_MSG_LENGTH]; + snprintf(message, RACHSYS_MSG_LENGTH, "[ #%s ] %s : %s",channel->name,sd->status.name, msg); + clif_chsys_msg(channel,sd,message); +} + +/* + * Read and verify configuration in confif_filename + * Assign table value with value + */ +void channel_read_config(void) { + config_t channels_conf; + config_setting_t *chsys = NULL; + const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name + + if (conf_read_file(&channels_conf, config_filename)) + return; + + chsys = config_lookup(&channels_conf, "chsys"); + + if (chsys != NULL) { + config_setting_t *settings = config_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; + int ally_enabled = 0, local_enabled = 0, + local_autojoin = 0, ally_autojoin = 0, + allow_user_channel_creation = 0; + + if( !config_setting_lookup_string(settings, "map_local_channel_name", &local_name) ) + local_name = "map"; + safestrncpy(raChSys.local_name, local_name, RACHSYS_NAME_LENGTH); + + if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_name) ) + ally_name = "ally"; + safestrncpy(raChSys.ally_name, ally_name, RACHSYS_NAME_LENGTH); + + config_setting_lookup_bool(settings, "map_local_channel", &local_enabled); + config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); + + if( local_enabled ) + raChSys.local = true; + if( ally_enabled ) + raChSys.ally = true; + + config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); + config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); + + if( local_autojoin ) + raChSys.local_autojoin = true; + if( ally_autojoin ) + raChSys.ally_autojoin = true; + + config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); + + if( allow_user_channel_creation ) + raChSys.allow_user_channel_creation = true; + + if( (colors = config_setting_get_member(settings, "colors")) != NULL ) { + int color_count = config_setting_length(colors); + CREATE( raChSys.colors, unsigned long, color_count ); + CREATE( raChSys.colors_name, char *, color_count ); + for(i = 0; i < color_count; i++) { + config_setting_t *color = config_setting_get_elem(colors, i); + + CREATE( raChSys.colors_name[i], char, RACHSYS_NAME_LENGTH ); + + safestrncpy(raChSys.colors_name[i], config_setting_name(color), RACHSYS_NAME_LENGTH); + + raChSys.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0); + raChSys.colors[i] = (raChSys.colors[i] & 0x0000FF) << 16 | (raChSys.colors[i] & 0x00FF00) | (raChSys.colors[i] & 0xFF0000) >> 16;//RGB to BGR + } + raChSys.colors_count = color_count; + } + + config_setting_lookup_string(settings, "map_local_channel_color", &local_color); + + for (k = 0; k < raChSys.colors_count; k++) { + if( strcmpi(raChSys.colors_name[k],local_color) == 0 ) + break; + } + + if( k < raChSys.colors_count ) { + raChSys.local_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for channel 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); + raChSys.local = false; + } + + config_setting_lookup_string(settings, "ally_channel_color", &ally_color); + + for (k = 0; k < raChSys.colors_count; k++) { + if( strcmpi(raChSys.colors_name[k],ally_color) == 0 ) + break; + } + + if( k < raChSys.colors_count ) { + raChSys.ally_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for channel 'ally_channel_color', disabling '#%s'...\n",local_color,ally_name); + raChSys.ally = false; + } + + if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) { + int channel_count = config_setting_length(channels); + + for(i = 0; i < channel_count; i++) { + config_setting_t *channel = config_setting_get_elem(channels, i); + const char *name = config_setting_name(channel); + const char *color = config_setting_get_string_elem(channels,i); + struct raChSysCh *chd; + + for (k = 0; k < raChSys.colors_count; k++) { + if( strcmpi(raChSys.colors_name[k],color) == 0 ) + break; + } + if( k == raChSys.colors_count ) { + ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); + continue; + } + if( strcmpi(name,raChSys.local_name) == 0 || strcmpi(name,raChSys.ally_name) == 0 || strdb_exists(channel_db, name) ) { + ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); + continue; + + } + CREATE( chd, struct raChSysCh, 1 ); + + safestrncpy(chd->name, name, RACHSYS_NAME_LENGTH); + chd->type = raChSys_PUBLIC; + + channel_create(chd,NULL,NULL,k); + } + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel_db), config_filename); + config_destroy(&channels_conf); + } +} + +/* + * Initialise db and read config + */ +int do_init_channel(void) { + channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, RACHSYS_NAME_LENGTH); + raChSys.ally = raChSys.local = raChSys.ally_autojoin = raChSys.local_autojoin = false; + channel_read_config(); + return 0; +} + +/* + * Close all and cleanup + */ +void do_final_channel(void) { + DBIterator *iter; + struct raChSysCh *channel; + int i=0; + + iter = db_iterator(channel_db); + for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) { + channel_delete(channel); + } + dbi_destroy(iter); + + for(i = 0; i < raChSys.colors_count; i++) { + aFree(raChSys.colors_name[i]); + } + + if( raChSys.colors_count ) { + aFree(raChSys.colors_name); + aFree(raChSys.colors); + } + + db_destroy(channel_db); +} \ No newline at end of file Index: src/map/channel.h =================================================================== --- src/map/channel.h (revision 0) +++ src/map/channel.h (revision 0) @@ -0,0 +1,71 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef CHANNEL_H +#define CHANNEL_H + +#include "pc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RACHSYS_NAME_LENGTH 20 +#define RACHSYS_MSG_LENGTH 150 + +enum raChSysChOpt { + raChSys_OPT_BASE = 0, + raChSys_OPT_ANNOUNCE_JOIN = 1, +}; + +enum raChSysChType { + raChSys_PUBLIC = 0, + raChSys_PRIVATE = 1, + raChSys_MAP = 2, + raChSys_ALLY = 3, +}; + +struct { + unsigned long *colors; + char **colors_name; + unsigned char colors_count; + bool local, ally; + bool local_autojoin, ally_autojoin; + char local_name[RACHSYS_NAME_LENGTH], ally_name[RACHSYS_NAME_LENGTH]; + unsigned char local_color, ally_color; + bool closing; + bool allow_user_channel_creation; +} raChSys; + +struct raChSysCh { + char name[RACHSYS_NAME_LENGTH]; + char pass[RACHSYS_NAME_LENGTH]; + unsigned char color; + DBMap *users; + unsigned int opt; + unsigned int owner; + enum raChSysChType type; + uint16 m; +}; + +DBMap* channel_get_db(void); + +void channel_create(struct raChSysCh *channel, char *name, char *pass, unsigned char color); +void channel_delete(struct raChSysCh *channel); + +void channel_join(struct raChSysCh *channel, struct map_session_data *sd); +void channel_mjoin(struct map_session_data *sd); +void channel_left(struct raChSysCh *channel, struct map_session_data *sd); + +void channel_send(struct raChSysCh *channel, struct map_session_data *sd, char *msg); +void channel_read_config(void); + +int do_init_channel(void); +void do_final_channel(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CHANNEL_H */ + Index: src/map/unit.c =================================================================== --- src/map/unit.c (revision 17265) +++ src/map/unit.c (working copy) @@ -18,6 +18,7 @@ #include "mercenary.h" #include "elemental.h" #include "skill.h" +#include "channel.h" #include "clif.h" #include "duel.h" #include "npc.h" @@ -2298,11 +2299,11 @@ struct guild *g = sd->guild, *sg; if( g ) { if( idb_exists(((struct raChSysCh *)g->channel)->users, sd->status.char_id) ) - clif_chsys_left((struct raChSysCh *)g->channel,sd); + channel_left((struct raChSysCh *)g->channel,sd); for (i = 0; i < MAX_GUILDALLIANCE; i++) { if( g->alliance[i].guild_id && (sg = guild_search(g->alliance[i].guild_id) ) ) { if( idb_exists(((struct raChSysCh *)sg->channel)->users, sd->status.char_id) ) - clif_chsys_left((struct raChSysCh *)sg->channel,sd); + channel_left((struct raChSysCh *)sg->channel,sd); break; } } @@ -2313,7 +2314,7 @@ uint8 ch_count = sd->channel_count; for( i = 0; i < ch_count; i++ ) { if( sd->channels[i] != NULL ) - clif_chsys_left(sd->channels[i],sd); + channel_left(sd->channels[i],sd); } if( raChSys.closing ) aFree(sd->channels);