viewing paste ra_chanrefac | Diff

Posted on the
  1. Index: conf/msg_conf/map_msg.conf
  2. ===================================================================
  3. --- conf/msg_conf/map_msg.conf	(revision 17267)
  4. +++ conf/msg_conf/map_msg.conf	(working copy)
  5. @@ -1457,6 +1457,7 @@
  6.  1433: Your global chat is now unbinded from the '#%s' channel.
  7.  1434: You're already in the '%s' channel.
  8.  1435: You're now in the '#%s' channel for '%s'.
  9. +1436: Channel pass can't be higher then %d.
  10.  
  11.  //Custom translations
  12.  //import: conf/msg_conf/import/map_msg_eng_conf.txt
  13. Index: src/map/unit.c
  14. ===================================================================
  15. --- src/map/unit.c	(revision 17267)
  16. +++ src/map/unit.c	(working copy)
  17. @@ -18,6 +18,7 @@
  18.  #include "mercenary.h"
  19.  #include "elemental.h"
  20.  #include "skill.h"
  21. +#include "channel.h"
  22.  #include "clif.h"
  23.  #include "duel.h"
  24.  #include "npc.h"
  25. @@ -2294,31 +2295,8 @@
  26.  			if( sd->duel_invite > 0 )
  27.  				duel_reject(sd->duel_invite, sd);
  28.  
  29. -			if( raChSys.ally && sd->status.guild_id ) {
  30. -				struct guild *g = sd->guild, *sg;
  31. -				if( g ) {
  32. -					if( idb_exists(((struct raChSysCh *)g->channel)->users, sd->status.char_id) )
  33. -						clif_chsys_left((struct raChSysCh *)g->channel,sd);
  34. -					for (i = 0; i < MAX_GUILDALLIANCE; i++) {
  35. -						if( g->alliance[i].guild_id && (sg = guild_search(g->alliance[i].guild_id) ) ) {
  36. -							if( idb_exists(((struct raChSysCh *)sg->channel)->users, sd->status.char_id) )
  37. -								clif_chsys_left((struct raChSysCh *)sg->channel,sd);
  38. -							break;
  39. -						}
  40. -					}
  41. -				}
  42. -			}
  43. +			channel_pcquit(sd,0xF); //leave all chan
  44.  
  45. -			if( sd->channel_count ) {
  46. -				uint8 ch_count = sd->channel_count;
  47. -				for( i = 0; i < ch_count; i++ ) {
  48. -					if( sd->channels[i] != NULL )
  49. -						clif_chsys_left(sd->channels[i],sd);
  50. -				}
  51. -				if( raChSys.closing )
  52. -					aFree(sd->channels);
  53. -			}
  54. -
  55.  			// Notify friends that this char logged out. [Skotlex]
  56.  			map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
  57.  			party_send_logout(sd);
  58. Index: src/map/status.c
  59. ===================================================================
  60. --- src/map/status.c	(revision 17267)
  61. +++ src/map/status.c	(working copy)
  62. @@ -10091,7 +10091,7 @@
  63.  			int hp =  rnd()%600 + 200;
  64.  			struct block_list* src = map_id2bl(sce->val2);
  65.  			if( src && bl && bl->type == BL_MOB ){
  66. -				mob_log_damage( (TBL_MOB*)bl, src, sd || hp < status->hp ? hp : status->hp - 1 ); 
  67. +				mob_log_damage( (TBL_MOB*)bl, src, sd || hp < status->hp ? hp : status->hp - 1 );
  68.  			}
  69.  			map_freeblock_lock();
  70.  			status_fix_damage(src, bl, sd||hp<status->hp?hp:status->hp-1, 1);
  71. Index: src/map/Makefile.in
  72. ===================================================================
  73. --- src/map/Makefile.in	(revision 17267)
  74. +++ src/map/Makefile.in	(working copy)
  75. @@ -17,7 +17,7 @@
  76.  	storage.o skill.o atcommand.o battle.o battleground.o \
  77.  	intif.o trade.o party.o vending.o guild.o pet.o \
  78.  	log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \
  79. -	buyingstore.o searchstore.o duel.o pc_groups.o elemental.o cashshop.o
  80. +	buyingstore.o searchstore.o duel.o pc_groups.o elemental.o cashshop.o channel.o
  81.  MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
  82.  	obj_sql/mapreg_sql.o
  83.  MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
  84. @@ -25,7 +25,7 @@
  85.  	storage.h skill.h atcommand.h battle.h battleground.h \
  86.  	intif.h trade.h party.h vending.h guild.h pet.h \
  87.  	log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \
  88. -	buyingstore.h searchstore.h duel.h pc_groups.h elemental.h cashshop.h \
  89. +	buyingstore.h searchstore.h duel.h pc_groups.h elemental.h cashshop.h channel.h\
  90.  	../config/core.h ../config/renewal.h ../config/secure.h ../config/const.h \
  91.  	../config/classes/general.h
  92.  
  93. @@ -91,10 +91,10 @@
  94.  # missing object files
  95.  ../common/obj_all/common.a:
  96.  	@$(MAKE) -C ../common sql
  97. -    
  98. +
  99.  ../common/obj_sql/common_sql.a:
  100.  	@$(MAKE) -C ../common sql
  101. -        
  102. +
  103.  MT19937AR_OBJ:
  104.  	@$(MAKE) -C ../../3rdparty/mt19937ar
  105.  
  106. Index: src/map/pc.c
  107. ===================================================================
  108. --- src/map/pc.c	(revision 17267)
  109. +++ src/map/pc.c	(working copy)
  110. @@ -16,6 +16,7 @@
  111.  #include "atcommand.h" // get_atcommand_level()
  112.  #include "battle.h" // battle_config
  113.  #include "battleground.h"
  114. +#include "channel.h"
  115.  #include "chrif.h"
  116.  #include "clif.h"
  117.  #include "date.h" // is_day_of_*()
  118. @@ -1249,7 +1250,7 @@
  119.  		}
  120.  
  121.  		clif_changeoption( &sd->bl );
  122. -	} 
  123. +	}
  124.  
  125.  	return 1;
  126.  }
  127. @@ -4782,9 +4783,7 @@
  128.  			vending_closevending(sd);
  129.  		}
  130.  
  131. -		if( raChSys.local && map[sd->bl.m].channel && idb_exists(map[sd->bl.m].channel->users, sd->status.char_id) ) {
  132. -			clif_chsys_left(map[sd->bl.m].channel,sd);
  133. -		}
  134. +		channel_pcquit(sd,4); //quit map chan
  135.  	}
  136.  
  137.  	if( m < 0 )
  138. @@ -9604,7 +9603,7 @@
  139.  	FILE *fp;
  140.  	char line[24000],*p;
  141.  
  142. -    //reset
  143. +	//reset
  144.  	memset(exp_table,0,sizeof(exp_table));
  145.  	memset(max_level,0,sizeof(max_level));
  146.  
  147. @@ -9651,7 +9650,7 @@
  148.  		//Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
  149.  		//The reasoning behind the -2 is this... if the max level is 5, then the array
  150.  		//should look like this:
  151. -	   //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
  152. +		//0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
  153.  		while ((ui = max_level[job][type]) >= 2 && exp_table[job][type][ui-2] <= 0)
  154.  			max_level[job][type]--;
  155.  		if (max_level[job][type] < maxlv) {
  156. @@ -9762,7 +9761,7 @@
  157.  	fclose(fp);
  158.  	ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","attr_fix.txt");
  159.  
  160. -    // reset then read statspoint
  161. +	 // reset then read statspoint
  162.  	memset(statp,0,sizeof(statp));
  163.  	i=1;
  164.  
  165. Index: src/map/atcommand.c
  166. ===================================================================
  167. --- src/map/atcommand.c	(revision 17267)
  168. +++ src/map/atcommand.c	(working copy)
  169. @@ -17,6 +17,7 @@
  170.  #include "atcommand.h"
  171.  #include "battle.h"
  172.  #include "chat.h"
  173. +#include "channel.h"
  174.  #include "clif.h"
  175.  #include "chrif.h"
  176.  #include "duel.h"
  177. @@ -5621,28 +5622,7 @@
  178.  		status_change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0);
  179.  	}
  180.  
  181. -	// Leave all chat channels.
  182. -	if( raChSys.ally && sd->status.guild_id ) {
  183. -		struct guild *g = sd->guild, *sg;
  184. -		if( g ) {
  185. -			if( idb_exists(((struct raChSysCh *)g->channel)->users, sd->status.char_id) )
  186. -				clif_chsys_left((struct raChSysCh *)g->channel,sd);
  187. -			for (i = 0; i < MAX_GUILDALLIANCE; i++) {
  188. -				if( g->alliance[i].guild_id && (sg = guild_search(g->alliance[i].guild_id) ) ) {
  189. -					if( idb_exists(((struct raChSysCh *)sg->channel)->users, sd->status.char_id) )
  190. -						clif_chsys_left((struct raChSysCh *)sg->channel,sd);
  191. -					break;
  192. -				}
  193. -			}
  194. -		}
  195. -	}
  196. -	if( sd->channel_count ) { //quit all chan
  197. -		uint8 count = sd->channel_count;
  198. -		for( i = 0; i < count; i++ ) {
  199. -			if( sd->channels[i] != NULL )
  200. -				clif_chsys_left(sd->channels[i],sd);
  201. -		}
  202. -	}
  203. +	channel_pcquit(sd,0xF); //leave all chan
  204.  	clif_authfail_fd(sd->fd, 15);
  205.  
  206.  	return 0;
  207. @@ -8782,251 +8762,113 @@
  208.  }
  209.  
  210.  /* Channel System [Ind] */
  211. -ACMD_FUNC(join)
  212. -{
  213. -	struct raChSysCh *channel;
  214. -	char name[RACHSYS_NAME_LENGTH], pass[RACHSYS_NAME_LENGTH];
  215. -	DBMap* channel_db = clif_get_channel_db();
  216. +ACMD_FUNC(join){
  217. +	struct Channel *channel;
  218. +	char chname[CHAN_NAME_LENGTH], pass[CHAN_NAME_LENGTH];
  219.  
  220. -	if( !message || !*message || sscanf(message, "%s %s", name, pass) < 1 ) {
  221. +	if( !message || !*message || sscanf(message, "%s %s", chname, pass) < 1 ) {
  222.  		sprintf(atcmd_output, msg_txt(sd,1399),command); // Unknown Channel (usage: %s <#channel_name>)
  223.  		clif_displaymessage(fd, atcmd_output);
  224.  		return -1;
  225.  	}
  226. -	if( raChSys.local && strcmpi(name + 1, raChSys.local_name) == 0 ) {
  227. -		if( !map[sd->bl.m].channel ) {
  228. -			clif_chsys_mjoin(sd);
  229. -			return 0;
  230. -		} else
  231. -			channel = map[sd->bl.m].channel;
  232. -	} else if( raChSys.ally && sd->status.guild_id && strcmpi(name + 1, raChSys.ally_name) == 0 ) {
  233. -		struct guild *g = sd->guild;
  234. -		if( !g ) return -1;/* unlikely, but we wont let it crash anyway. */
  235. -		channel = (struct raChSysCh *)g->channel;
  236. -	} else if( !( channel = strdb_get(channel_db, name + 1) ) ) {
  237. -		sprintf(atcmd_output, msg_txt(sd,1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>)
  238. -		clif_displaymessage(fd, atcmd_output);
  239. -		return -1;
  240. -	}
  241. -
  242. -	if( idb_exists(channel->users, sd->status.char_id) ) {
  243. -		sprintf(atcmd_output, msg_txt(sd,1434),name); // You're already in the '%s' channel.
  244. -		clif_displaymessage(fd, atcmd_output);
  245. -		return -1;
  246. -	}
  247. -	if( channel->pass[0] != '\0'  && strcmp(channel->pass,pass) != 0 ) {
  248. -		if( pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) {
  249. -			sd->stealth = true;
  250. -		} else {
  251. -			sprintf(atcmd_output, msg_txt(sd,1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> <password>)
  252. -			clif_displaymessage(fd, atcmd_output);
  253. -			return -1;
  254. -		}
  255. -	}
  256. -
  257. -	if( !( channel->opt & raChSys_OPT_ANNOUNCE_JOIN ) ) {
  258. -		sprintf(atcmd_output, msg_txt(sd,1403),name); // You're now in the '%s' channel.
  259. -		clif_displaymessage(fd, atcmd_output);
  260. -	}
  261. -
  262. -	clif_chsys_join(channel,sd);
  263. -
  264. -	return 0;
  265. +	return channel_pcjoin(sd, chname, pass);
  266.  }
  267.  
  268. -static inline void atcmd_channel_help(struct map_session_data *sd, const char *command, bool can_create)
  269. +static inline void atcmd_channel_help(struct map_session_data *sd, const char *command)
  270.  {
  271.  	int fd = sd->fd;
  272. +	bool can_delete = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN);
  273. +	bool can_create =  can_delete|Channel_Config.user_chenable;
  274.  	clif_displaymessage(fd, msg_txt(sd,1414));// ---- Available options:
  275. +
  276. +	//option create
  277.  	if( can_create ) {
  278.  		sprintf(atcmd_output, msg_txt(sd,1415),command);// * %s create <#channel_name> <channel_password>
  279.  		clif_displaymessage(fd, atcmd_output);
  280.  		clif_displaymessage(fd, msg_txt(sd,1416));// -- Creates a new channel.
  281.  	}
  282. +
  283. +	//option delete
  284. +	if(can_delete){
  285. +		sprintf(atcmd_output, "* %s delete <channel_name>",command);// * %s delete <channel_name>
  286. +		clif_displaymessage(fd, atcmd_output);
  287. +		clif_displaymessage(fd, "Force people leave and destroy the specified channel");
  288. +	}
  289. +
  290. +	//option list
  291.  	sprintf(atcmd_output, msg_txt(sd,1417),command);// * %s list
  292.  	clif_displaymessage(fd, atcmd_output);
  293.  	clif_displaymessage(fd, msg_txt(sd,1418));// -- Lists all public channels.
  294. +	sprintf(atcmd_output, "* %s list mine",command);// * %s list mine
  295. +	clif_displaymessage(fd, atcmd_output);
  296. +	clif_displaymessage(fd, "List all your joined channel");
  297.  	if( can_create ) {
  298.  		sprintf(atcmd_output, msg_txt(sd,1419),command);// * %s list colors
  299.  		clif_displaymessage(fd, atcmd_output);
  300.  		clif_displaymessage(fd, msg_txt(sd,1420));// -- Lists all available colors for custom channels.
  301. +	}
  302. +
  303. +	//option setcolor
  304. +	if(can_create){
  305.  		sprintf(atcmd_output, msg_txt(sd,1421),command);// * %s setcolor <#channel_name> <color_name>
  306.  		clif_displaymessage(fd, atcmd_output);
  307.  		clif_displaymessage(fd, msg_txt(sd,1422));// -- Changes channel text to the specified color (channel owners only).
  308.  	}
  309. +
  310. +	//option join
  311. +	sprintf(atcmd_output, "* %s join <channel_name> <channel_password>",command);// * %s delete <channel_name>
  312. +	clif_displaymessage(fd, atcmd_output);
  313. +	clif_displaymessage(fd, "join specified channel");
  314. +
  315. +	//option leave
  316.  	sprintf(atcmd_output, msg_txt(sd,1423),command);// * %s leave <#channel_name>
  317.  	clif_displaymessage(fd, atcmd_output);
  318.  	clif_displaymessage(fd, msg_txt(sd,1424));// -- Leaves the specified channel.
  319. +
  320. +	//option bindto
  321.  	sprintf(atcmd_output, msg_txt(sd,1427),command);// * %s bindto <#channel_name>
  322.  	clif_displaymessage(fd, atcmd_output);
  323.  	clif_displaymessage(fd, msg_txt(sd,1428));// -- Binds your global chat to the specified channel, sending all global messages to that channel.
  324. +
  325. +	//option unbind
  326.  	sprintf(atcmd_output, msg_txt(sd,1429),command);// * %s unbind
  327.  	clif_displaymessage(fd, atcmd_output);
  328.  	clif_displaymessage(fd, msg_txt(sd,1430));// -- Unbinds your global chat from the attached channel, if any.
  329. +
  330.  	sprintf(atcmd_output, msg_txt(sd,1404),command); // %s failed.
  331.  	clif_displaymessage(fd, atcmd_output);
  332.  }
  333.  
  334. -ACMD_FUNC(channel)
  335. -{
  336. -	struct raChSysCh *channel;
  337. -	char key[RACHSYS_NAME_LENGTH], sub1[RACHSYS_NAME_LENGTH], sub2[RACHSYS_NAME_LENGTH], sub3[RACHSYS_NAME_LENGTH];
  338. +ACMD_FUNC(channel) {
  339. +	struct Channel *channel;
  340. +	char key[CHAN_NAME_LENGTH], sub1[CHAN_NAME_LENGTH], sub2[CHAN_NAME_LENGTH], sub3[CHAN_NAME_LENGTH];
  341.  	unsigned char k = 0;
  342. -	DBMap* channel_db = clif_get_channel_db();
  343. +	DBMap* channel_db = channel_get_db();
  344.  	sub1[0] = sub2[0] = sub3[0] = '\0';
  345.  
  346.  	if( !message || !*message || sscanf(message, "%s %s %s %s", key, sub1, sub2, sub3) < 1 ) {
  347. -		atcmd_channel_help(sd,command,( raChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ));
  348. +		atcmd_channel_help(sd,command);
  349.  		return 0;
  350.  	}
  351.  
  352. -	if( strcmpi(key,"create") == 0 && ( raChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) ) {
  353. -		if( sub1[0] != '#' ) {
  354. -			clif_displaymessage(fd, msg_txt(sd,1405));// Channel name must start with '#'.
  355. -			return -1;
  356. -		} else if ( strlen(sub1) < 3 || strlen(sub1) > RACHSYS_NAME_LENGTH ) {
  357. -			sprintf(atcmd_output, msg_txt(sd,1406), RACHSYS_NAME_LENGTH);// Channel length must be between 3 and %d.
  358. -			clif_displaymessage(fd, atcmd_output);
  359. -			return -1;
  360. -		} else if ( sub3[0] != '\0' ) {
  361. -			clif_displaymessage(fd, msg_txt(sd,1408)); // Channel password may not contain spaces.
  362. -			return -1;
  363. -		}
  364. -		if( strcmpi(sub1 + 1,raChSys.local_name) == 0 || strcmpi(sub1 + 1,raChSys.ally_name) == 0 || strdb_exists(channel_db, sub1 + 1) ) {
  365. -			sprintf(atcmd_output, msg_txt(sd,1407), sub1);// Channel '%s' is not available.
  366. -			clif_displaymessage(fd, atcmd_output);
  367. -			return -1;
  368. -		}
  369. -
  370. -		CREATE( channel, struct raChSysCh, 1 );
  371. -
  372. -		clif_chsys_create(channel,sub1 + 1,sub2,0);
  373. -
  374. -		channel->owner = sd->status.char_id;
  375. -		channel->type = raChSys_PRIVATE;
  376. -
  377. -		if( !( channel->opt & raChSys_OPT_ANNOUNCE_JOIN ) ) {
  378. -			sprintf(atcmd_output, msg_txt(sd,1403),sub1); // You're now in the '%s' channel.
  379. -			clif_displaymessage(fd, atcmd_output);
  380. -		}
  381. -
  382. -		clif_chsys_join(channel,sd);
  383. -
  384. +	if( strcmpi(key,"create") == 0 && ( Channel_Config.user_chenable || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) ) {
  385. +		return channel_pccreate(sd,sub1,sub2);
  386. +	} else if( strcmpi(key,"delete") == 0 && pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) {
  387. +		return channel_pcdelete(sd,sub1);
  388.  	} else if ( strcmpi(key,"list") == 0 ) {
  389. -		if( sub1[0] != '\0' && strcmpi(sub1,"colors") == 0 ) {
  390. -			char mout[40];
  391. -			for( k = 0; k < raChSys.colors_count; k++ ) {
  392. -				unsigned short msg_len = 1;
  393. -				msg_len += sprintf(mout, "[ %s list colors ] : %s",command,raChSys.colors_name[k]);
  394. -
  395. -				WFIFOHEAD(fd,msg_len + 12);
  396. -				WFIFOW(fd,0) = 0x2C1;
  397. -				WFIFOW(fd,2) = msg_len + 12;
  398. -				WFIFOL(fd,4) = 0;
  399. -				WFIFOL(fd,8) = raChSys.colors[k];
  400. -				safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
  401. -				WFIFOSET(fd, msg_len + 12);
  402. -			}
  403. -		} else {
  404. -			DBIterator *iter;
  405. -			bool show_all = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ? true : false;
  406. -			clif_displaymessage(fd, msg_txt(sd,1410)); // ---- Public Channels ----
  407. -			if( raChSys.local ) {
  408. -				sprintf(atcmd_output, msg_txt(sd,1409), raChSys.local_name, map[sd->bl.m].channel ? db_size(map[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
  409. -				clif_displaymessage(fd, atcmd_output);
  410. -			}
  411. -			if( raChSys.ally && sd->status.guild_id ) {
  412. -				struct guild *g = sd->guild;
  413. -				if( !g ) return -1;
  414. -				sprintf(atcmd_output, msg_txt(sd,1409), raChSys.ally_name, db_size(((struct raChSysCh *)g->channel)->users));// - #%s ( %d users )
  415. -				clif_displaymessage(fd, atcmd_output);
  416. -			}
  417. -			iter = db_iterator(channel_db);
  418. -			for(channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) {
  419. -				if( show_all || channel->type == raChSys_PUBLIC ) {
  420. -					sprintf(atcmd_output, msg_txt(sd,1409), channel->name, db_size(channel->users));// - #%s (%d users)
  421. -					clif_displaymessage(fd, atcmd_output);
  422. -				}
  423. -			}
  424. -			dbi_destroy(iter);
  425. -		}
  426. +		return channel_display_list(sd,sub1);
  427.  	} else if ( strcmpi(key,"setcolor") == 0 ) {
  428. -
  429. -		if( sub1[0] != '#' ) {
  430. -			clif_displaymessage(fd, msg_txt(sd,1405));// Channel name must start with '#'.
  431. -			return -1;
  432. -		}
  433. -
  434. -		if( !(channel = strdb_get(channel_db, sub1 + 1)) ) {
  435. -			sprintf(atcmd_output, msg_txt(sd,1407), sub1);// Channel '%s' is not available.
  436. -			clif_displaymessage(fd, atcmd_output);
  437. -			return -1;
  438. -		}
  439. -
  440. -		if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) {
  441. -			sprintf(atcmd_output, msg_txt(sd,1412), sub1);// You're not the owner of channel '%s'.
  442. -			clif_displaymessage(fd, atcmd_output);
  443. -			return -1;
  444. -		}
  445. -
  446. -		for( k = 0; k < raChSys.colors_count; k++ ) {
  447. -			if( strcmpi(sub2,raChSys.colors_name[k]) == 0 )
  448. -				break;
  449. -		}
  450. -		if( k == raChSys.colors_count ) {
  451. -			sprintf(atcmd_output, msg_txt(sd,1411), sub2);// Unknown color '%s'.
  452. -			clif_displaymessage(fd, atcmd_output);
  453. -			return -1;
  454. -		}
  455. -		channel->color = k;
  456. -		sprintf(atcmd_output, msg_txt(sd,1413),sub1,raChSys.colors_name[k]);// '%s' channel color updated to '%s'.
  457. -		clif_displaymessage(fd, atcmd_output);
  458. -	} else if ( strcmpi(key,"leave") == 0 ) {
  459. -
  460. -		if( sub1[0] != '#' ) {
  461. -			clif_displaymessage(fd, msg_txt(sd,1405));// Channel name must start with '#'.
  462. -			return -1;
  463. -		}
  464. -
  465. -		ARR_FIND(0, sd->channel_count, k, strcmpi(sub1+1,sd->channels[k]->name) == 0);
  466. -		if( k == sd->channel_count ) {
  467. -			sprintf(atcmd_output, msg_txt(sd,1425),sub1);// You're not part of the '%s' channel.
  468. -			clif_displaymessage(fd, atcmd_output);
  469. -			return -1;
  470. -		}
  471. -		clif_chsys_left(sd->channels[k],sd);
  472. -		sprintf(atcmd_output, msg_txt(sd,1426),sub1); // You've left the '%s' channel.
  473. -		clif_displaymessage(fd, atcmd_output);
  474. +		return channel_pccolor(sd, sub1, sub2);
  475. +	} else if ( strcmpi(key,"join") == 0 ) {
  476. +		return channel_pcjoin(sd, sub1, sub2);
  477. +	}else if ( strcmpi(key,"leave") == 0 ) {
  478. +		return channel_pcleave(sd, sub1);
  479.  	} else if ( strcmpi(key,"bindto") == 0 ) {
  480. -
  481. -		if( sub1[0] != '#' ) {
  482. -			clif_displaymessage(fd, msg_txt(sd,1405));// Channel name must start with '#'.
  483. -			return -1;
  484. -		}
  485. -
  486. -		ARR_FIND(0, sd->channel_count, k, strcmpi(sub1+1,sd->channels[k]->name) == 0);
  487. -		if( k == sd->channel_count ) {
  488. -			sprintf(atcmd_output, msg_txt(sd,1425),sub1);// You're not part of the '%s' channel.
  489. -			clif_displaymessage(fd, atcmd_output);
  490. -			return -1;
  491. -		}
  492. -
  493. -		sd->gcbind = sd->channels[k];
  494. -		sprintf(atcmd_output, msg_txt(sd,1431),sub1); // Your global chat is now binded to the '%s' channel.
  495. -		clif_displaymessage(fd, atcmd_output);
  496. +		return channel_pcbind(sd, sub1);
  497.  	} else if ( strcmpi(key,"unbind") == 0 ) {
  498. -
  499. -		if( sd->gcbind == NULL ) {
  500. -			clif_displaymessage(fd, msg_txt(sd,1432));// Your global chat is not binded to any channel.
  501. -			return -1;
  502. -		}
  503. -
  504. -		sprintf(atcmd_output, msg_txt(sd,1433),sd->gcbind->name); // Your global chat is now unbinded from the '#%s' channel.
  505. -		clif_displaymessage(fd, atcmd_output);
  506. -
  507. -		sd->gcbind = NULL;
  508. +		return channel_pcunbind(sd);
  509.  	} else {
  510. -		atcmd_channel_help(sd,command,( raChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ));
  511. +		atcmd_channel_help(sd,command);
  512.  	}
  513.  
  514.  	return 0;
  515. @@ -9038,17 +8880,9 @@
  516.  
  517.  	if( !message || !*message ) {
  518.  		char mout[40];
  519. -		for( k = 0; k < raChSys.colors_count; k++ ) {
  520. -			unsigned short msg_len = 1;
  521. -			msg_len += sprintf(mout, "[ %s ] : %s",command,raChSys.colors_name[k]);
  522. -
  523. -			WFIFOHEAD(fd,msg_len + 12);
  524. -			WFIFOW(fd,0) = 0x2C1;
  525. -			WFIFOW(fd,2) = msg_len + 12;
  526. -			WFIFOL(fd,4) = 0;
  527. -			WFIFOL(fd,8) = raChSys.colors[k];
  528. -			safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
  529. -			WFIFOSET(fd, msg_len + 12);
  530. +		for( k = 0; k < Channel_Config.colors_count; k++ ) {
  531. +			sprintf(mout, "[ %s ] : %s",command,Channel_Config.colors_name[k]);
  532. +			clif_colormes(sd,k,mout);
  533.  		}
  534.  		return -1;
  535.  	}
  536. @@ -9059,11 +8893,8 @@
  537.  		return 0;
  538.  	}
  539.  
  540. -	for( k = 0; k < raChSys.colors_count; k++ ) {
  541. -		if( strcmpi(message,raChSys.colors_name[k]) == 0 )
  542. -			break;
  543. -	}
  544. -	if( k == raChSys.colors_count ) {
  545. +	ARR_FIND(0,Channel_Config.colors_count,k,( strcmpi(message,Channel_Config.colors_name[k]) == 0 ));
  546. +	if( k == Channel_Config.colors_count ) {
  547.  		sprintf(atcmd_output, msg_txt(sd,1411), message);// Unknown color '%s'.
  548.  		clif_displaymessage(fd, atcmd_output);
  549.  		return -1;
  550. Index: src/map/pc.h
  551. ===================================================================
  552. --- src/map/pc.h	(revision 17267)
  553. +++ src/map/pc.h	(working copy)
  554. @@ -499,9 +499,9 @@
  555.  	int shadowform_id;
  556.  
  557.  	/* Channel System [Ind] */
  558. -	struct raChSysCh **channels;
  559. +	struct Channel **channels;
  560.  	unsigned char channel_count;
  561. -	struct raChSysCh *gcbind;
  562. +	struct Channel *gcbind;
  563.  	bool stealth;
  564.  	unsigned char fontcolor; /* debug-only */
  565.  
  566. Index: src/map/clif.c
  567. ===================================================================
  568. --- src/map/clif.c	(revision 17267)
  569. +++ src/map/clif.c	(working copy)
  570. @@ -44,6 +44,7 @@
  571.  #include "mail.h"
  572.  #include "quest.h"
  573.  #include "cashshop.h"
  574. +#include "channel.h"
  575.  
  576.  #include <stdio.h>
  577.  #include <stdlib.h>
  578. @@ -53,8 +54,6 @@
  579.  
  580.  /* for clif_clearunit_delayed */
  581.  static struct eri *delay_clearunit_ers;
  582. -static DBMap* channel_db; // channels
  583. -DBMap* clif_get_channel_db(void){ return channel_db; }
  584.  
  585.  //#define DUMP_UNKNOWN_PACKET
  586.  //#define DUMP_INVALID_PACKET
  587. @@ -5490,52 +5489,11 @@
  588.  		aFree(buf);
  589.  }
  590.  
  591. -/*==========================================
  592. - * Channel System
  593. - *------------------------------------------*/
  594. -void clif_chsys_create(struct raChSysCh *channel, char *name, char *pass, unsigned char color) {
  595. -	channel->users = idb_alloc(DB_OPT_BASE);
  596. -	if( name )
  597. -		safestrncpy(channel->name, name, RACHSYS_NAME_LENGTH);
  598. -	channel->color = color;
  599. -	if( !pass )
  600. -		channel->pass[0] = '\0';
  601. -	else
  602. -		safestrncpy(channel->pass, pass, RACHSYS_NAME_LENGTH);
  603. -
  604. -	channel->opt = raChSys_OPT_BASE;
  605. -
  606. -	if( channel->type != raChSys_MAP && channel->type != raChSys_ALLY )
  607. -		strdb_put(channel_db, channel->name, channel);
  608. -}
  609. -
  610. -void clif_chsys_join(struct raChSysCh *channel, struct map_session_data *sd) {
  611. -	RECREATE(sd->channels, struct raChSysCh *, ++sd->channel_count);
  612. -	sd->channels[ sd->channel_count - 1 ] = channel;
  613. -	idb_put(channel->users, sd->status.char_id, sd);
  614. -
  615. -	if( sd->stealth ) {
  616. -		sd->stealth = false;
  617. -	} else if( channel->opt & raChSys_OPT_ANNOUNCE_JOIN ) {
  618. -		char message[60];
  619. -		sprintf(message, "#%s '%s' joined",channel->name,sd->status.name);
  620. -		clif_chsys_msg(channel,sd,message);
  621. -	}
  622. -
  623. -	/* someone is cheating, we kindly disconnect the bastard */
  624. -	if( sd->channel_count > 200 ) {
  625. -		set_eof(sd->fd);
  626. -	}
  627. -}
  628. -
  629. -void clif_chsys_send(struct raChSysCh *channel, struct map_session_data *sd, char *msg) {
  630. -	char message[150];
  631. -	snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg);
  632. -	clif_chsys_msg(channel,sd,message);
  633. -}
  634. -
  635. -void clif_chsys_msg(struct raChSysCh *channel, struct map_session_data *sd, char *msg) {
  636. -	DBIterator *iter = db_iterator(channel->users);
  637. +/*
  638. + * Display *msg from *sd to all *users in channel
  639. + */
  640. +void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char *msg) {
  641. +	DBIterator *iter;
  642.  	struct map_session_data *user;
  643.  	unsigned short msg_len = strlen(msg) + 1;
  644.  
  645. @@ -5543,9 +5501,10 @@
  646.  	WFIFOW(sd->fd,0) = 0x2C1;
  647.  	WFIFOW(sd->fd,2) = msg_len + 12;
  648.  	WFIFOL(sd->fd,4) = 0;
  649. -	WFIFOL(sd->fd,8) = raChSys.colors[channel->color];
  650. +	WFIFOL(sd->fd,8) = Channel_Config.colors[channel->color];
  651.  	safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len);
  652.  
  653. +	iter = db_iterator(channel->users);
  654.  	for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
  655.  		if( user->fd == sd->fd )
  656.  			continue;
  657. @@ -5553,231 +5512,11 @@
  658.  		memcpy(WFIFOP(user->fd,0), WFIFOP(sd->fd,0), msg_len + 12);
  659.  		WFIFOSET(user->fd, msg_len + 12);
  660.  	}
  661. +	dbi_destroy(iter);
  662.  
  663.  	WFIFOSET(sd->fd, msg_len + 12);
  664. -
  665. -	dbi_destroy(iter);
  666.  }
  667.  
  668. -void clif_chsys_mjoin(struct map_session_data *sd) {
  669. -	if( !map[sd->bl.m].channel ) {
  670. -		CREATE(map[sd->bl.m].channel, struct raChSysCh , 1);
  671. -		safestrncpy(map[sd->bl.m].channel->name, raChSys.local_name, RACHSYS_NAME_LENGTH);
  672. -		map[sd->bl.m].channel->type = raChSys_MAP;
  673. -		map[sd->bl.m].channel->m = sd->bl.m;
  674. -
  675. -		clif_chsys_create(map[sd->bl.m].channel,NULL,NULL,raChSys.local_color);
  676. -	}
  677. -	clif_chsys_join(map[sd->bl.m].channel,sd);
  678. -
  679. -	if( !( map[sd->bl.m].channel->opt & raChSys_OPT_ANNOUNCE_JOIN ) ) {
  680. -		char mout[60];
  681. -		sprintf(mout, msg_txt(sd,1435),raChSys.local_name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'.
  682. -		clif_disp_onlyself(sd, mout, strlen(mout));
  683. -	}
  684. -}
  685. -
  686. -void clif_chsys_left(struct raChSysCh *channel, struct map_session_data *sd) {
  687. -	unsigned char i;
  688. -	idb_remove(channel->users,sd->status.char_id);
  689. -
  690. -	if( channel == sd->gcbind )
  691. -		sd->gcbind = NULL;
  692. -
  693. -	if( !db_size(channel->users) && channel->type == raChSys_PRIVATE ) {
  694. -		clif_chsys_delete(channel);
  695. -	} else if( !raChSys.closing && (channel->opt & raChSys_OPT_ANNOUNCE_JOIN) ) {
  696. -		char message[60];
  697. -		sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
  698. -		clif_chsys_msg(channel,sd,message);
  699. -	}
  700. -
  701. -	ARR_FIND(0, sd->channel_count, i, sd->channels[i] == channel);
  702. -	if( i < sd->channel_count ) {
  703. -		unsigned char cursor = 0;
  704. -		sd->channels[i] = NULL;
  705. -		for( i = 0; i < sd->channel_count; i++ ) {
  706. -			if( sd->channels[i] == NULL )
  707. -				continue;
  708. -			if( cursor != i )
  709. -				sd->channels[cursor] = sd->channels[i];
  710. -			cursor++;
  711. -		}
  712. -		if ( !(sd->channel_count = cursor) ) {
  713. -			aFree(sd->channels);
  714. -			sd->channels = NULL;
  715. -		}
  716. -	}
  717. -
  718. -}
  719. -
  720. -void clif_chsys_delete(struct raChSysCh *channel) {
  721. -	if( db_size(channel->users) && !raChSys.closing ) {
  722. -		struct map_session_data *sd;
  723. -		unsigned char i;
  724. -		DBIterator *iter = db_iterator(channel->users);
  725. -		for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { //for all users
  726. -			ARR_FIND(0, sd->channel_count, i, sd->channels[i] == channel); //found cur chan
  727. -			if( i < sd->channel_count ) {
  728. -				unsigned char cursor = 0;
  729. -				sd->channels[i] = NULL;
  730. -				for( i = 0; i < sd->channel_count; i++ ) { //move down links
  731. -					if( sd->channels[i] == NULL )
  732. -						continue;
  733. -					if( cursor != i )
  734. -						sd->channels[cursor] = sd->channels[i];
  735. -					cursor++;
  736. -				}
  737. -				if ( !(sd->channel_count = cursor) ) { //news chan count = total
  738. -					aFree(sd->channels);
  739. -					sd->channels = NULL;
  740. -				}
  741. -			}
  742. -		}
  743. -		dbi_destroy(iter);
  744. -	}
  745. -	db_destroy(channel->users);
  746. -	if( channel->m ) {
  747. -		map[channel->m].channel = NULL;
  748. -		aFree(channel);
  749. -	} else if ( channel->type == raChSys_ALLY )
  750. -		aFree(channel);
  751. -	else if( !raChSys.closing )
  752. -		strdb_remove(channel_db, channel->name);
  753. -}
  754. -
  755. -void clif_read_channels_config(void) {
  756. -	config_t channels_conf;
  757. -	config_setting_t *chsys = NULL;
  758. -	const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name
  759. -
  760. -	if (conf_read_file(&channels_conf, config_filename))
  761. -		return;
  762. -
  763. -	chsys = config_lookup(&channels_conf, "chsys");
  764. -
  765. -	if (chsys != NULL) {
  766. -		config_setting_t *settings = config_setting_get_elem(chsys, 0);
  767. -		config_setting_t *channels;
  768. -		config_setting_t *colors;
  769. -		int i,k;
  770. -		const char *local_name, *ally_name,
  771. -					*local_color, *ally_color;
  772. -		int ally_enabled = 0, local_enabled = 0,
  773. -			local_autojoin = 0, ally_autojoin = 0,
  774. -			allow_user_channel_creation = 0;
  775. -
  776. -		if( !config_setting_lookup_string(settings, "map_local_channel_name", &local_name) )
  777. -			local_name = "map";
  778. -		safestrncpy(raChSys.local_name, local_name, RACHSYS_NAME_LENGTH);
  779. -
  780. -		if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_name) )
  781. -			ally_name = "ally";
  782. -		safestrncpy(raChSys.ally_name, ally_name, RACHSYS_NAME_LENGTH);
  783. -
  784. -		config_setting_lookup_bool(settings, "map_local_channel", &local_enabled);
  785. -		config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
  786. -
  787. -		if( local_enabled )
  788. -			raChSys.local = true;
  789. -		if( ally_enabled )
  790. -			raChSys.ally = true;
  791. -
  792. -		config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
  793. -		config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
  794. -
  795. -		if( local_autojoin )
  796. -			raChSys.local_autojoin = true;
  797. -		if( ally_autojoin )
  798. -			raChSys.ally_autojoin = true;
  799. -
  800. -		config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
  801. -
  802. -		if( allow_user_channel_creation )
  803. -			raChSys.allow_user_channel_creation = true;
  804. -
  805. -		if( (colors = config_setting_get_member(settings, "colors")) != NULL ) {
  806. -			int color_count = config_setting_length(colors);
  807. -			CREATE( raChSys.colors, unsigned long, color_count );
  808. -			CREATE( raChSys.colors_name, char *, color_count );
  809. -			for(i = 0; i < color_count; i++) {
  810. -				config_setting_t *color = config_setting_get_elem(colors, i);
  811. -
  812. -				CREATE( raChSys.colors_name[i], char, RACHSYS_NAME_LENGTH );
  813. -
  814. -				safestrncpy(raChSys.colors_name[i], config_setting_name(color), RACHSYS_NAME_LENGTH);
  815. -
  816. -				raChSys.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0);
  817. -				raChSys.colors[i] = (raChSys.colors[i] & 0x0000FF) << 16 | (raChSys.colors[i] & 0x00FF00) | (raChSys.colors[i] & 0xFF0000) >> 16;//RGB to BGR
  818. -			}
  819. -			raChSys.colors_count = color_count;
  820. -		}
  821. -
  822. -		config_setting_lookup_string(settings, "map_local_channel_color", &local_color);
  823. -
  824. -		for (k = 0; k < raChSys.colors_count; k++) {
  825. -			if( strcmpi(raChSys.colors_name[k],local_color) == 0 )
  826. -				break;
  827. -		}
  828. -
  829. -		if( k < raChSys.colors_count ) {
  830. -			raChSys.local_color = k;
  831. -		} else {
  832. -			ShowError("channels.conf: unknown color '%s' for channel 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name);
  833. -			raChSys.local = false;
  834. -		}
  835. -
  836. -		config_setting_lookup_string(settings, "ally_channel_color", &ally_color);
  837. -
  838. -		for (k = 0; k < raChSys.colors_count; k++) {
  839. -			if( strcmpi(raChSys.colors_name[k],ally_color) == 0 )
  840. -				break;
  841. -		}
  842. -
  843. -		if( k < raChSys.colors_count ) {
  844. -			raChSys.ally_color = k;
  845. -		} else {
  846. -			ShowError("channels.conf: unknown color '%s' for channel 'ally_channel_color', disabling '#%s'...\n",local_color,ally_name);
  847. -			raChSys.ally = false;
  848. -		}
  849. -
  850. -		if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) {
  851. -			int channel_count = config_setting_length(channels);
  852. -
  853. -			for(i = 0; i < channel_count; i++) {
  854. -				config_setting_t *channel = config_setting_get_elem(channels, i);
  855. -				const char *name = config_setting_name(channel);
  856. -				const char *color = config_setting_get_string_elem(channels,i);
  857. -				struct raChSysCh *chd;
  858. -
  859. -				for (k = 0; k < raChSys.colors_count; k++) {
  860. -					if( strcmpi(raChSys.colors_name[k],color) == 0 )
  861. -						break;
  862. -				}
  863. -				if( k == raChSys.colors_count ) {
  864. -					ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name);
  865. -					continue;
  866. -				}
  867. -				if( strcmpi(name,raChSys.local_name) == 0 || strcmpi(name,raChSys.ally_name) == 0 || strdb_exists(channel_db, name) ) {
  868. -					ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name);
  869. -					continue;
  870. -
  871. -				}
  872. -				CREATE( chd, struct raChSysCh, 1 );
  873. -
  874. -				safestrncpy(chd->name, name, RACHSYS_NAME_LENGTH);
  875. -				chd->type = raChSys_PUBLIC;
  876. -
  877. -				clif_chsys_create(chd,NULL,NULL,k);
  878. -			}
  879. -		}
  880. -
  881. -		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel_db), config_filename);
  882. -		config_destroy(&channels_conf);
  883. -	}
  884. -}
  885. -
  886. -
  887.  /// Displays heal effect (ZC_RECOVERY).
  888.  /// 013d <var id>.W <amount>.W
  889.  /// var id:
  890. @@ -9564,8 +9303,8 @@
  891.  		status_calc_pc(sd, false); // Some conditions are map-dependent so we must recalculate
  892.  		sd->state.changemap = false;
  893.  
  894. -		if( raChSys.local && raChSys.local_autojoin && !map[sd->bl.m].flag.chsysnolocalaj ) {
  895. -			clif_chsys_mjoin(sd);
  896. +		if( Channel_Config.map_enable && Channel_Config.map_autojoin && !map[sd->bl.m].flag.chmautojoin) {
  897. +			channel_mjoin(sd); //join new map
  898.  		}
  899.  	}
  900.  
  901. @@ -9867,23 +9606,12 @@
  902.  	}
  903.  
  904.  	if( sd->gcbind ) {
  905. -		clif_chsys_send(sd->gcbind,sd,message);
  906. +		channel_send(sd->gcbind,sd,message);
  907.  		return;
  908.  	} else if ( sd->fontcolor && !sd->chatID ) {
  909.  		char mout[200];
  910. -		unsigned char mylen = 1;
  911. -
  912. -		mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
  913. -
  914. -		WFIFOHEAD(fd,mylen + 12);
  915. -		WFIFOW(fd,0) = 0x2C1;
  916. -		WFIFOW(fd,2) = mylen + 12;
  917. -		WFIFOL(fd,4) = sd->bl.id;
  918. -		WFIFOL(fd,8) = raChSys.colors[sd->fontcolor - 1];
  919. -		safestrncpy((char*)WFIFOP(fd,12), mout, mylen);
  920. -		clif_send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
  921. -		WFIFOL(fd,4) = -sd->bl.id;
  922. -		WFIFOSET(fd, mylen + 12);
  923. +		snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
  924. +		clif_colormes(sd,sd->fontcolor-1,mout);
  925.  		return;
  926.  	}
  927.  
  928. @@ -10256,30 +9984,32 @@
  929.  			return;
  930.  		}
  931.  	} else if( target[0] == '#' ) {
  932. -		struct raChSysCh *channel = NULL;
  933. +		struct Channel *channel = NULL;
  934.  		char* chname = target;
  935.  
  936. -		chname++;
  937. -
  938. -		if( raChSys.local && strcmpi(chname, raChSys.local_name) == 0 ) {
  939. -			if( !map[sd->bl.m].channel ) {
  940. -				clif_chsys_mjoin(sd);
  941. -			}
  942. +		if(Channel_Config.map_enable
  943. +			&& (strcmpi(chname + 1,Channel_Config.map_chname) == 0)) {
  944. +			if( !map[sd->bl.m].channel ) channel_mjoin(sd);
  945.  			channel = map[sd->bl.m].channel;
  946. -		} else if( raChSys.ally && sd->status.guild_id && strcmpi(chname, raChSys.ally_name) == 0 ) {
  947. -			struct guild *g = sd->guild;
  948. -			if( !g ) return;
  949. -			channel = (struct raChSysCh *)g->channel;
  950.  		}
  951. -		if( channel || (channel = strdb_get(channel_db,chname)) ) {
  952. -			unsigned char k;
  953. -			ARR_FIND(0, sd->channel_count, k, sd->channels[k] == channel);
  954. -			if( k < sd->channel_count ) {
  955. -				clif_chsys_send(channel,sd,message);
  956. -			} else if( channel->pass[0] == '\0' ) {
  957. -				clif_chsys_join(channel,sd);
  958. -				clif_chsys_send(channel,sd,message);
  959. -			} else {
  960. +		else if(Channel_Config.ally_enable
  961. +			&& (strcmpi(chname + 1,Channel_Config.ally_chname) == 0)
  962. +			&& sd->guild) {
  963. +			struct guild *g=sd->guild;
  964. +			if(g->channel == NULL) channel_gjoin(sd,3);
  965. +			channel = g->channel;
  966. +		}
  967. +		else channel = channel_name2channel(chname);
  968. +
  969. +		if(channel){
  970. +			if(channel_pc_haschan(sd,channel)>=0){ //we are in the chan
  971. +				channel_send(channel,sd,message);
  972. +			}
  973. +			else if( channel->pass[0] == '\0' ) { //no pass needed
  974. +				channel_join(channel,sd);
  975. +				channel_send(channel,sd,message);
  976. +			}
  977. +			else {
  978.  				clif_displaymessage(fd, msg_txt(sd,1402)); //You're not in that channel, type '@join <#channel_name>'
  979.  			}
  980.  			return;
  981. @@ -17374,34 +17104,9 @@
  982.  	add_timer_func_list(clif_delayquit, "clif_delayquit");
  983.  
  984.  	delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR);
  985. -
  986. -	channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, RACHSYS_NAME_LENGTH);
  987. -	raChSys.ally = raChSys.local = raChSys.ally_autojoin = raChSys.local_autojoin = false;
  988. -	clif_read_channels_config();
  989. -
  990.  	return 0;
  991.  }
  992.  
  993.  void do_final_clif(void) {
  994. -	DBIterator *iter = db_iterator(channel_db);
  995. -	struct raChSysCh *channel;
  996. -	unsigned char i;
  997. -
  998. -	for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) {
  999. -		clif_chsys_delete(channel);
  1000. -	}
  1001. -
  1002. -	dbi_destroy(iter);
  1003. -
  1004. -	for(i = 0; i < raChSys.colors_count; i++) {
  1005. -		aFree(raChSys.colors_name[i]);
  1006. -	}
  1007. -
  1008. -	if( raChSys.colors_count ) {
  1009. -		aFree(raChSys.colors_name);
  1010. -		aFree(raChSys.colors);
  1011. -	}
  1012. -
  1013. -	db_destroy(channel_db);
  1014.  	ers_destroy(delay_clearunit_ers);
  1015.  }
  1016. Index: src/map/npc.c
  1017. ===================================================================
  1018. --- src/map/npc.c	(revision 17267)
  1019. +++ src/map/npc.c	(working copy)
  1020. @@ -2138,7 +2138,7 @@
  1021.  		return strchr(start,'\n');// skip and continue
  1022.  	}
  1023.  
  1024. -	if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) { 
  1025. +	if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
  1026.  		ShowWarning("npc_parse_warp: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
  1027.  	}
  1028.  
  1029. @@ -2209,7 +2209,7 @@
  1030.  
  1031.  	if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
  1032.  		ShowWarning("npc_parse_shop: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
  1033. -	} 
  1034. +	}
  1035.  
  1036.  	if( !strcasecmp(w2,"cashshop") )
  1037.  		type = CASHSHOP;
  1038. @@ -3429,7 +3429,7 @@
  1039.  	else if (!strcmpi(w3,"reset"))
  1040.  		map[m].flag.reset=state;
  1041.  	else if (!strcmpi(w3,"nomapchannelautojoin"))
  1042. -		map[m].flag.chsysnolocalaj = state;
  1043. +		map[m].flag.chmautojoin = state;
  1044.  	else
  1045.  		ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer));
  1046.  
  1047. Index: src/map/clif.h
  1048. ===================================================================
  1049. --- src/map/clif.h	(revision 17267)
  1050. +++ src/map/clif.h	(working copy)
  1051. @@ -6,7 +6,9 @@
  1052.  
  1053.  #include "../common/cbasetypes.h"
  1054.  #include "../common/db.h" //dbmap
  1055. +
  1056.  //#include "../common/mmo.h"
  1057. +struct Channel;
  1058.  struct item;
  1059.  struct storage_data;
  1060.  struct guild_storage;
  1061. @@ -775,56 +777,8 @@
  1062.  unsigned long color_table[COLOR_MAX];
  1063.  int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg);
  1064.  
  1065. -/**
  1066. - * Channel System
  1067. - **/
  1068. -#define RACHSYS_NAME_LENGTH 20
  1069. +void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char *msg);
  1070.  
  1071. -enum raChSysChOpt {
  1072. -	raChSys_OPT_BASE				= 0,
  1073. -	raChSys_OPT_ANNOUNCE_JOIN	= 1,
  1074. -};
  1075. -
  1076. -enum raChSysChType {
  1077. -	raChSys_PUBLIC	= 0,
  1078. -	raChSys_PRIVATE	= 1,
  1079. -	raChSys_MAP		= 2,
  1080. -	raChSys_ALLY		= 3,
  1081. -};
  1082. -
  1083. -struct {
  1084. -	unsigned long *colors;
  1085. -	char **colors_name;
  1086. -	unsigned char colors_count;
  1087. -	bool local, ally;
  1088. -	bool local_autojoin, ally_autojoin;
  1089. -	char local_name[RACHSYS_NAME_LENGTH], ally_name[RACHSYS_NAME_LENGTH];
  1090. -	unsigned char local_color, ally_color;
  1091. -	bool closing;
  1092. -	bool allow_user_channel_creation;
  1093. -} raChSys;
  1094. -
  1095. -struct raChSysCh {
  1096. -	char name[RACHSYS_NAME_LENGTH];
  1097. -	char pass[RACHSYS_NAME_LENGTH];
  1098. -	unsigned char color;
  1099. -	DBMap *users;
  1100. -	unsigned int opt;
  1101. -	unsigned int owner;
  1102. -	enum raChSysChType type;
  1103. -	uint16 m;
  1104. -};
  1105. -
  1106. -struct DBMap* clif_get_channel_db(void);
  1107. -void clif_chsys_create(struct raChSysCh *channel, char *name, char *pass, unsigned char color);
  1108. -void clif_chsys_msg(struct raChSysCh *channel, struct map_session_data *sd, char *msg);
  1109. -void clif_chsys_send(struct raChSysCh *channel, struct map_session_data *sd, char *msg);
  1110. -void clif_chsys_join(struct raChSysCh *channel, struct map_session_data *sd);
  1111. -void clif_chsys_left(struct raChSysCh *channel, struct map_session_data *sd);
  1112. -void clif_chsys_delete(struct raChSysCh *channel);
  1113. -void clif_chsys_mjoin(struct map_session_data *sd);
  1114. -void clif_read_channels_config(void);
  1115. -
  1116.  #define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
  1117.  
  1118.  #endif /* _CLIF_H_ */
  1119. Index: src/map/battle.c
  1120. ===================================================================
  1121. --- src/map/battle.c	(revision 17267)
  1122. +++ src/map/battle.c	(working copy)
  1123. @@ -3460,7 +3460,7 @@
  1124.  
  1125.  #ifdef RENEWAL
  1126.  		if( flag.cri ){
  1127. -			ATK_ADDRATE( sd->bonus.crit_atk_rate >= 100 ? sd->bonus.crit_atk_rate - 60 : 40 ); 
  1128. +			ATK_ADDRATE( sd->bonus.crit_atk_rate >= 100 ? sd->bonus.crit_atk_rate - 60 : 40 );
  1129.  		}
  1130.  #endif
  1131.  
  1132. Index: src/map/map.c
  1133. ===================================================================
  1134. --- src/map/map.c	(revision 17267)
  1135. +++ src/map/map.c	(working copy)
  1136. @@ -48,6 +48,8 @@
  1137.  #include "log.h"
  1138.  #include "mail.h"
  1139.  #include "cashshop.h"
  1140. +#include "channel.h"
  1141. +
  1142.  #include <stdio.h>
  1143.  #include <stdlib.h>
  1144.  #include <string.h>
  1145. @@ -1429,6 +1431,7 @@
  1146.  
  1147.  	nullpo_ret(item_data);
  1148.  
  1149. +
  1150.  	if(!map_searchrandfreecell(m,&x,&y,flags&2?1:0))
  1151.  		return 0;
  1152.  	r=rnd();
  1153. @@ -3546,7 +3549,7 @@
  1154.  	struct s_mapiterator* iter;
  1155.  
  1156.  	ShowStatus("Terminating...\n");
  1157. -	raChSys.closing = true;
  1158. +	Channel_Config.closing = true;
  1159.  
  1160.  	//Ladies and babies first.
  1161.  	iter = mapit_getallusers();
  1162. @@ -3562,8 +3565,7 @@
  1163.  		ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, map_num, map[i].name);
  1164.  		if (map[i].m >= 0) {
  1165.  			map_foreachinmap(cleanup_sub, i, BL_ALL);
  1166. -			if( map[i].channel != NULL )
  1167. -				clif_chsys_delete((struct raChSysCh *)map[i].channel);
  1168. +			channel_delete((struct Channel *)map[i].channel);
  1169.  		}
  1170.  	}
  1171.  	ShowStatus("Cleaned up %d maps."CL_CLL"\n", map_num);
  1172. @@ -3594,6 +3596,7 @@
  1173.  	do_final_duel();
  1174.  	do_final_elemental();
  1175.  	do_final_cashshop();
  1176. +	do_final_channel(); //should be called after final guild
  1177.  
  1178.  	map_db->destroy(map_db, map_db_final);
  1179.  
  1180. @@ -3876,6 +3879,7 @@
  1181.  	do_init_atcommand();
  1182.  	do_init_battle();
  1183.  	do_init_instance();
  1184. +	do_init_channel();
  1185.  	do_init_chrif();
  1186.  	do_init_clif();
  1187.  	do_init_script();
  1188. Index: src/map/map.h
  1189. ===================================================================
  1190. --- src/map/map.h	(revision 17267)
  1191. +++ src/map/map.h	(working copy)
  1192. @@ -17,7 +17,7 @@
  1193.  
  1194.  struct npc_data;
  1195.  struct item_data;
  1196. -struct raChSysCh;
  1197. +struct Channel;
  1198.  
  1199.  enum E_MAPSERVER_ST {
  1200.  	MAPSERVER_ST_RUNNING = CORE_ST_LAST,
  1201. @@ -567,7 +567,7 @@
  1202.  		unsigned guildlock :1;
  1203.  		unsigned src4instance : 1; // To flag this map when it's used as a src map for instances
  1204.  		unsigned reset :1; // [Daegaladh]
  1205. -		unsigned chsysnolocalaj : 1;
  1206. +		unsigned chmautojoin : 1; //prevent to auto join map channel
  1207.  	} flag;
  1208.  	struct point save;
  1209.  	struct npc_data *npc[MAX_NPC_PER_MAP];
  1210. @@ -595,7 +595,7 @@
  1211.  	int instance_src_map;
  1212.  
  1213.  	/* rAthena Local Chat */
  1214. -	struct raChSysCh *channel;
  1215. +	struct Channel *channel;
  1216.  };
  1217.  
  1218.  /// Stores information about a remote map (for multi-mapserver setups).
  1219. Index: src/map/guild.c
  1220. ===================================================================
  1221. --- src/map/guild.c	(revision 17267)
  1222. +++ src/map/guild.c	(working copy)
  1223. @@ -21,6 +21,7 @@
  1224.  #include "mob.h"
  1225.  #include "intif.h"
  1226.  #include "clif.h"
  1227. +#include "channel.h"
  1228.  #include "skill.h"
  1229.  #include "log.h"
  1230.  
  1231. @@ -499,7 +500,7 @@
  1232.  	DBData data;
  1233.  	struct map_session_data *sd;
  1234.  	bool guild_new = false;
  1235. -	void *aChSysSave = NULL;
  1236. +	struct Channel *channel;
  1237.  
  1238.  	nullpo_ret(sg);
  1239.  
  1240. @@ -507,40 +508,6 @@
  1241.  		guild_new = true;
  1242.  		g=(struct guild *)aCalloc(1,sizeof(struct guild));
  1243.  		idb_put(guild_db,sg->guild_id,g);
  1244. -		if( raChSys.ally ) {
  1245. -			struct raChSysCh *channel;
  1246. -
  1247. -			CREATE(channel, struct raChSysCh , 1);
  1248. -			safestrncpy(channel->name, raChSys.ally_name, RACHSYS_NAME_LENGTH);
  1249. -			channel->type = raChSys_ALLY;
  1250. -
  1251. -			clif_chsys_create(channel,NULL,NULL,raChSys.ally_color);
  1252. -			if( raChSys.ally_autojoin ) {
  1253. -				struct s_mapiterator* iter = mapit_getallusers();
  1254. -
  1255. -				for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) {
  1256. -					if( sd->status.guild_id ) {
  1257. -						if( sd->status.guild_id == sg->guild_id ) {
  1258. -							clif_chsys_join(channel,sd);
  1259. -							sd->guild = g;
  1260. -							continue;
  1261. -						}
  1262. -
  1263. -						for (i = 0; i < MAX_GUILDALLIANCE; i++) {
  1264. -							if( sg->alliance[i].guild_id == sd->status.guild_id ) {
  1265. -								clif_chsys_join(channel,sd);
  1266. -								break;
  1267. -							}
  1268. -						}
  1269. -					}
  1270. -				}
  1271. -
  1272. -				mapit_free(iter);
  1273. -			}
  1274. -
  1275. -			aChSysSave = (void*)channel;
  1276. -
  1277. -		}
  1278.  		before=*sg;
  1279.  		//Perform the check on the user because the first load
  1280.  		guild_check_member(sg);
  1281. @@ -558,13 +525,9 @@
  1282.  		}
  1283.  	} else {
  1284.  		before=*g;
  1285. -		if( g->channel )
  1286. -			aChSysSave = g->channel;
  1287.  	}
  1288.  	memcpy(g,sg,sizeof(struct guild));
  1289.  
  1290. -	g->channel = aChSysSave;
  1291. -
  1292.  	if(g->max_member > MAX_GUILD) {
  1293.  		ShowError("guild_recv_info: Received guild with %d members, but MAX_GUILD is only %d. Extra guild-members have been lost!\n", g->max_member, MAX_GUILD);
  1294.  		g->max_member = MAX_GUILD;
  1295. @@ -581,11 +544,23 @@
  1296.  			bm++;
  1297.  	}
  1298.  
  1299. +	if(Channel_Config.ally_enable){
  1300. +		channel = g->channel;
  1301. +		if(!channel){
  1302. +			channel = channel_create(Channel_Config.ally_chname,NULL,Channel_Config.ally_chcolor,CHAN_TYPE_ALLY);
  1303. +			channel->gid = g->guild_id;
  1304. +			g->channel = channel;
  1305. +			channel_ajoin(g);
  1306. +		}
  1307. +	}
  1308.  	for (i = 0; i < g->max_member; i++) { //Transmission of information at all members
  1309.  		sd = g->member[i].sd;
  1310.  		if( sd==NULL )
  1311.  			continue;
  1312.  		sd->guild = g;
  1313. +		if(Channel_Config.ally_autojoin ) {
  1314. +			channel_gjoin(sd,3); //make all member join guildchan+allieschan
  1315. +		}
  1316.  
  1317.  		if (before.guild_lv != g->guild_lv || bm != m ||
  1318.  			before.max_member != g->max_member) {
  1319. @@ -755,16 +730,8 @@
  1320.  		g->member[i].sd = sd;
  1321.  		sd->guild = g;
  1322.  
  1323. -		if( raChSys.ally && raChSys.ally_autojoin ) {
  1324. -			struct guild* sg = NULL;
  1325. -			clif_chsys_join((struct raChSysCh*)g->channel,sd);
  1326. -
  1327. -			for (i = 0; i < MAX_GUILDALLIANCE; i++) {
  1328. -				if( g->alliance[i].guild_id && (sg = guild_search(g->alliance[i].guild_id) ) ) {
  1329. -					clif_chsys_join((struct raChSysCh*)sg->channel,sd);
  1330. -					break;
  1331. -				}
  1332. -			}
  1333. +		if( Channel_Config.ally_enable && Channel_Config.ally_autojoin ) {
  1334. +			channel_gjoin(sd,3);
  1335.  		}
  1336.  	}
  1337.  }
  1338. @@ -909,13 +876,7 @@
  1339.  		if (sd->state.storage_flag == 2) //Close the guild storage.
  1340.  			storage_guild_storageclose(sd);
  1341.  		guild_send_dot_remove(sd);
  1342. -		if( raChSys.ally ) {
  1343. -			uint8 ch_count = sd->channel_count;
  1344. -			for (i = 0; i < ch_count; i++) {
  1345. -				if( sd->channels[i] && sd->channels[i]->type == raChSys_ALLY )
  1346. -					clif_chsys_left(sd->channels[i],sd);
  1347. -			}
  1348. -		}
  1349. +		channel_pcquit(sd,3); //leave guild and ally chan
  1350.  		sd->status.guild_id = 0;
  1351.  		sd->guild = NULL;
  1352.  		sd->guild_emblem_id = 0;
  1353. @@ -1578,9 +1539,9 @@
  1354.  		return 0;
  1355.  	}
  1356.  
  1357. -    for (i = 0; i < MAX_GUILDALLIANCE; i++) { // checking relations
  1358. +	for (i = 0; i < MAX_GUILDALLIANCE; i++) { // checking relations
  1359.  		if(g->alliance[i].guild_id==tsd->status.guild_id){
  1360. -            if (g->alliance[i].opposition == 1) { // check if not already hostile
  1361. +			if (g->alliance[i].opposition == 1) { // check if not already hostile
  1362.  				clif_guild_oppositionack(sd,2);
  1363.  				return 0;
  1364.  			}
  1365. @@ -1592,7 +1553,7 @@
  1366.  		}
  1367.  	}
  1368.  
  1369. -    // inform other serv
  1370. +	// inform other serv
  1371.  	intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
  1372.  			sd->status.account_id,tsd->status.account_id,1 );
  1373.  	return 0;
  1374. @@ -1624,14 +1585,14 @@
  1375.  		sd[0]->guild_alliance_account=0;
  1376.  	}
  1377.  
  1378. -    if (flag & 0x70) { // failure
  1379. +	if (flag & 0x70) { // failure
  1380.  		for(i=0;i<2-(flag&1);i++)
  1381.  			if( sd[i]!=NULL )
  1382.  				clif_guild_allianceack(sd[i],((flag>>4)==i+1)?3:4);
  1383.  		return 0;
  1384.  	}
  1385.  
  1386. -    if (!(flag & 0x08)) { // new relationship
  1387. +	if (!(flag & 0x08)) { // new relationship
  1388.  		for(i=0;i<2-(flag&1);i++)
  1389.  		{
  1390.  			if(g[i]!=NULL)
  1391. @@ -1645,35 +1606,38 @@
  1392.  				}
  1393.  			}
  1394.  		}
  1395. -    } else { // remove relationship
  1396. +	} else { // remove relationship
  1397.  		for(i=0;i<2-(flag&1);i++)
  1398.  		{
  1399.  			if(g[i]!=NULL)
  1400.  			{
  1401. +				for(j=0;j<g[i]->max_member;j++) channel_pcquit(g[i]->member[j].sd,2); //leave all alliance chan
  1402.  				ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == guild_id[1-i] && g[i]->alliance[j].opposition == (flag&1) );
  1403.  				if( j < MAX_GUILDALLIANCE )
  1404.  					g[i]->alliance[j].guild_id = 0;
  1405.  			}
  1406. -            if (sd[i] != NULL) // notify players
  1407. +		if (sd[i] != NULL) // notify players
  1408.  				clif_guild_delalliance(sd[i],guild_id[1-i],(flag&1));
  1409.  		}
  1410.  	}
  1411.  
  1412. -    if ((flag & 0x0f) == 0) { // alliance notification
  1413. +	if ((flag & 0x0f) == 0) { // alliance notification
  1414.  		if( sd[1]!=NULL )
  1415.  			clif_guild_allianceack(sd[1],2);
  1416. -    } else if ((flag & 0x0f) == 1) { // enemy notification
  1417. +	} else if ((flag & 0x0f) == 1) { // enemy notification
  1418.  		if( sd[0]!=NULL )
  1419.  			clif_guild_oppositionack(sd[0],0);
  1420.  	}
  1421.  
  1422.  
  1423. -    for (i = 0; i < 2 - (flag & 1); i++) { // Retransmission of the relationship list to all members
  1424. +	for (i = 0; i < 2 - (flag & 1); i++) { // Retransmission of the relationship list to all members
  1425.  		struct map_session_data *sd;
  1426.  		if(g[i]!=NULL)
  1427.  			for(j=0;j<g[i]->max_member;j++)
  1428. -				if((sd=g[i]->member[j].sd)!=NULL)
  1429. +				if((sd=g[i]->member[j].sd)!=NULL){
  1430.  					clif_guild_allianceinfo(sd);
  1431. +					channel_gjoin(sd,2); //join ally join
  1432. +				}
  1433.  	}
  1434.  	return 0;
  1435.  }
  1436. @@ -1751,10 +1715,8 @@
  1437.  	guild_db->foreach(guild_db,guild_broken_sub,guild_id);
  1438.  	castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id);
  1439.  	guild_storage_delete(guild_id);
  1440. -	if( raChSys.ally ) {
  1441. -		if( g->channel != NULL ) {
  1442. -			clif_chsys_delete(( struct raChSysCh * )g->channel);
  1443. -		}
  1444. +	if( Channel_Config.ally_enable ) {
  1445. +		channel_delete(( struct Channel * )g->channel);
  1446.  	}
  1447.  	idb_remove(guild_db,guild_id);
  1448.  	return 0;
  1449. @@ -2203,10 +2165,8 @@
  1450.  	struct guild *g;
  1451.  
  1452.  	for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) {
  1453. -		if( g->channel != NULL )
  1454. -			clif_chsys_delete((struct raChSysCh *)g->channel);
  1455. +		channel_delete((struct Channel *)g->channel);
  1456.  	}
  1457. -
  1458.  	dbi_destroy(iter);
  1459.  
  1460.  	db_destroy(guild_db);
  1461. Index: src/map/channel.c
  1462. ===================================================================
  1463. --- src/map/channel.c	(revision 0)
  1464. +++ src/map/channel.c	(revision 0)
  1465. @@ -0,0 +1,803 @@
  1466. +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  1467. +// For more information, see LICENCE in the main folder
  1468. +
  1469. +#include "../common/cbasetypes.h"
  1470. +#include "../common/malloc.h"
  1471. +#include "../common/conf.h" //libconfig
  1472. +#include "../common/showmsg.h"
  1473. +#include "../common/strlib.h" //safestrncpy
  1474. +#include "../common/socket.h" //set_eof
  1475. +#include "../common/nullpo.h" //nullpo chk
  1476. +
  1477. +#include "map.h" //msg_conf
  1478. +#include "clif.h" //clif_chsys_msg
  1479. +#include "channel.h"
  1480. +#include "pc.h"
  1481. +
  1482. +#include <stdio.h>
  1483. +#include <stdlib.h>
  1484. +
  1485. +static DBMap* channel_db; // channels
  1486. +DBMap* channel_get_db(void){ return channel_db; } //private or public chat
  1487. +
  1488. +/*
  1489. + * Create *channel
  1490. + * - then add it in channel_db if type not map or ally
  1491. + */
  1492. +struct Channel* channel_create(char *name, char *pass, unsigned char color, enum Channel_Type chantype) {
  1493. +	struct Channel* channel;
  1494. +	CREATE( channel, struct Channel, 1 ); //will exit on fail allocation
  1495. +
  1496. +	channel->opt = CHAN_OPT_BASE;
  1497. +	channel->type = chantype;
  1498. +	channel->users = idb_alloc(DB_OPT_BASE);
  1499. +	if( name )
  1500. +		safestrncpy(channel->name, name, CHAN_NAME_LENGTH);
  1501. +	channel->color = color;
  1502. +	if( !pass )
  1503. +		channel->pass[0] = '\0';
  1504. +	else
  1505. +		safestrncpy(channel->pass, pass, CHAN_NAME_LENGTH);
  1506. +
  1507. +	ShowInfo("Create channel %s\n",channel->name);
  1508. +
  1509. +	if( channel->type != CHAN_TYPE_MAP && channel->type != CHAN_TYPE_ALLY)
  1510. +		strdb_put(channel_db, channel->name, channel);
  1511. +	return channel;
  1512. +}
  1513. +
  1514. +/*
  1515. + * Delete *channel
  1516. + * - check if ramin user in channel and make them all quit
  1517. + * -@TODO add return value
  1518. + */
  1519. +void channel_delete(struct Channel *channel) {
  1520. +	if(!channel)
  1521. +		return;
  1522. +	else if( db_size(channel->users)) {
  1523. +		struct map_session_data *sd;
  1524. +		DBIterator *iter = db_iterator(channel->users);
  1525. +		for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { //for all users
  1526. +			channel_clean(channel,sd,1); //make all quit
  1527. +		}
  1528. +		dbi_destroy(iter);
  1529. +	}
  1530. +	ShowInfo("Deleting channel %s\n",channel->name);
  1531. +
  1532. +	db_destroy(channel->users);
  1533. +	switch(channel->type){
  1534. +	case CHAN_TYPE_MAP:
  1535. +		map[channel->m].channel = NULL;
  1536. +		aFree(channel);
  1537. +		break;
  1538. +	case CHAN_TYPE_ALLY: {
  1539. +		struct guild *g = guild_search(channel->gid);
  1540. +		if(g) g->channel = NULL;
  1541. +		aFree(channel);
  1542. +		break;
  1543. +	}
  1544. +	default:
  1545. +		strdb_remove(channel_db, channel->name);
  1546. +		break;
  1547. +	}
  1548. +}
  1549. +
  1550. +/*
  1551. + * Make *sd join *channel
  1552. + * - add charid to channel user list
  1553. + * - add *channel to user channel list
  1554. + */
  1555. +void channel_join(struct Channel *channel, struct map_session_data *sd) {
  1556. +	if(!channel || !sd)
  1557. +		return;
  1558. +	if(channel_haspc(channel,sd)) //already in here
  1559. +		return;
  1560. +
  1561. +	RECREATE(sd->channels, struct Channel *, ++sd->channel_count);
  1562. +	sd->channels[ sd->channel_count - 1 ] = channel;
  1563. +	idb_put(channel->users, sd->status.char_id, sd);
  1564. +
  1565. +	if( sd->stealth ) {
  1566. +		sd->stealth = false;
  1567. +	} else if( channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) {
  1568. +		char message[60];
  1569. +		sprintf(message, "#%s '%s' joined",channel->name,sd->status.name);
  1570. +		clif_channel_msg(channel,sd,message);
  1571. +	}
  1572. +
  1573. +	if(channel->type == CHAN_TYPE_ALLY) ShowDebug("sd=%d join chan %s guilid %d\n",
  1574. +		sd->bl.id,channel->name,channel->gid);
  1575. +	else ShowDebug("sd=%d join chan %s\n",sd->bl.id,channel->name);
  1576. +
  1577. +	/* someone is cheating, we kindly disconnect the bastard */
  1578. +	if( sd->channel_count > 200 ) {
  1579. +		set_eof(sd->fd);
  1580. +	}
  1581. +}
  1582. +
  1583. +/*
  1584. + * Make *sd join the map channel
  1585. + * create the map_channel if not exist
  1586. + */
  1587. +void channel_mjoin(struct map_session_data *sd) {
  1588. +	if(!sd) return;
  1589. +
  1590. +	if( !map[sd->bl.m].channel ) {
  1591. +		map[sd->bl.m].channel = channel_create(Channel_Config.map_chname,NULL,Channel_Config.map_chcolor,CHAN_TYPE_MAP);
  1592. +		map[sd->bl.m].channel->m = sd->bl.m; //associate map
  1593. +	}
  1594. +	channel_join(map[sd->bl.m].channel,sd);
  1595. +
  1596. +	if( !( map[sd->bl.m].channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) ) {
  1597. +		char mout[60];
  1598. +		sprintf(mout, msg_txt(sd,1435),Channel_Config.map_chname,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'.
  1599. +		clif_disp_onlyself(sd, mout, strlen(mout));
  1600. +	}
  1601. +}
  1602. +
  1603. +/*
  1604. + * Make all ally member of guild g join our guild chan
  1605. + */
  1606. +void channel_ajoin(struct guild *g){
  1607. +	int i;
  1608. +	struct map_session_data *pl_sd;
  1609. +
  1610. +	if(!g || !g->channel) return;
  1611. +	for (i = 0; i < MAX_GUILDALLIANCE; i++){
  1612. +		struct guild *ag; //allied guld
  1613. +		struct guild_alliance *ga = &g->alliance[i]; //guild alliance
  1614. +		if(ga->guild_id && (ga->opposition==0) && (ag=guild_search(ga->guild_id))){
  1615. +			for (i = 0; i < ag->max_member; i++){ //load all guildmember
  1616. +				pl_sd = ag->member[i].sd;
  1617. +				if(channel_haspc(ag->channel,pl_sd) )  //only if they are in there own guildchan
  1618. +					channel_join(g->channel,pl_sd);
  1619. +			}
  1620. +		}
  1621. +	}
  1622. +}
  1623. +
  1624. +/*
  1625. + * Make *sd join the guild channel
  1626. + * create a chan guild if not exist
  1627. + */
  1628. +void channel_gjoin(struct map_session_data *sd, int flag){
  1629. +	struct Channel *channel;
  1630. +	struct guild *g;
  1631. +	int i;
  1632. +
  1633. +	if(!sd) return;
  1634. +
  1635. +	g = sd->guild;
  1636. +	if(!g) return;
  1637. +
  1638. +	channel = g->channel;
  1639. +	if(!channel){
  1640. +		channel = channel_create(Channel_Config.ally_chname,NULL,Channel_Config.ally_chcolor,CHAN_TYPE_ALLY);
  1641. +		channel->gid = g->guild_id;
  1642. +		g->channel = channel;
  1643. +		channel_ajoin(g);
  1644. +	}
  1645. +	if(flag&1) {
  1646. +		ShowDebug("join guild chan\n",sd->guild->guild_id);
  1647. +		channel_join(channel,sd);	//join our guild chat
  1648. +	}
  1649. +	if(flag&2){
  1650. +		ShowDebug("join all alliance chan\n"); //join allies chat
  1651. +		for (i = 0; i < MAX_GUILDALLIANCE; i++){
  1652. +			struct guild *ag; //allied guld
  1653. +			struct guild_alliance *ga = &g->alliance[i]; //guild alliance
  1654. +			if(ga->guild_id && (ga->opposition==0) && (ag=guild_search(ga->guild_id)) ) //only join allies
  1655. +				channel_join(ag->channel,sd);
  1656. +		}
  1657. +	}
  1658. +}
  1659. +
  1660. +/*
  1661. + * Make *sd leave *channel and cleanup association.
  1662. + * if no one remain in chat delete it (PRIVATE only atm)
  1663. + * @flag&1 called from delete do not recall delete
  1664. + */
  1665. +void channel_clean(struct Channel *channel, struct map_session_data *sd, int flag) {
  1666. +	unsigned char i;
  1667. +
  1668. +	if(!channel || !sd)
  1669. +		return;
  1670. +
  1671. +	if( channel == sd->gcbind )
  1672. +		sd->gcbind = NULL;
  1673. +
  1674. +	ARR_FIND(0, sd->channel_count, i, sd->channels[i] == channel);
  1675. +	if( i < sd->channel_count ) {
  1676. +		unsigned char cursor = i;
  1677. +		sd->channels[i] = NULL;
  1678. +		for(; i < sd->channel_count; i++ ) { //slice move list down
  1679. +			if( sd->channels[i] == NULL )
  1680. +				continue;
  1681. +			if(i != cursor)
  1682. +				sd->channels[cursor] = sd->channels[i];
  1683. +			cursor++;
  1684. +		}
  1685. +		if ( !(sd->channel_count = cursor) ) { //if in no more chan delete db
  1686. +			aFree(sd->channels);
  1687. +			sd->channels = NULL;
  1688. +		}
  1689. +	}
  1690. +
  1691. +	if(channel->type == CHAN_TYPE_ALLY) ShowDebug("sd=%d left chan %s guilid %d\n",
  1692. +		sd->bl.id,channel->name,channel->gid);
  1693. +	else ShowDebug("sd=%d left chan %s\n",sd->bl.id,channel->name);
  1694. +
  1695. +	idb_remove(channel->users,sd->status.char_id); //remove user for channel user list
  1696. +	if( !db_size(channel->users) && !(flag&1) )
  1697. +		channel_delete(channel);
  1698. +}
  1699. +
  1700. +/*
  1701. + *  type&1 : quit guild chan
  1702. + *  type&2 : quit ally chans
  1703. + *  type&4 : quit map chan
  1704. + *  type&8 : quit all users joined chan
  1705. + */
  1706. +void channel_pcquit(struct map_session_data *sd, int type){
  1707. +	int i;
  1708. +
  1709. +	//On closing state we could have clean all chan by sd but pcquit is more used to free unit when
  1710. +	//he quit a map_server, not call in map_quit cause we need to cleanup when we switch map-server as well
  1711. +	if(!sd) return;
  1712. +
  1713. +	// Leave all chat channels.
  1714. +	if(type&(1|2) && Channel_Config.ally_enable && sd->guild){ //quit guild and ally chan
  1715. +		struct guild *g = sd->guild;
  1716. +		if(type&1 && channel_haspc(g->channel,sd) ){ //leave guild chan
  1717. +			ShowDebug("leave all guild chan\n");
  1718. +			channel_clean(g->channel,sd,0);
  1719. +		}
  1720. +		if(type&2){
  1721. +			struct guild *ag; //allied guild
  1722. +			ShowDebug("leave all alliance chan\n");
  1723. +			for (i = 0; i < MAX_GUILDALLIANCE; i++) { //leave all alliance chan
  1724. +				if( g->alliance[i].guild_id && (ag = guild_search(g->alliance[i].guild_id) ) ) {
  1725. +					if( channel_haspc(ag->channel,sd) )
  1726. +						channel_clean(ag->channel,sd,0);
  1727. +					break;
  1728. +				}
  1729. +			}
  1730. +		}
  1731. +	}
  1732. +	if(type&4 && Channel_Config.map_enable && channel_haspc(map[sd->bl.m].channel,sd)){ //quit map chan
  1733. +		channel_clean(map[sd->bl.m].channel,sd,0);
  1734. +	}
  1735. +	if(type&8 && sd->channel_count ) { //quit all chan
  1736. +		uint8 count = sd->channel_count;
  1737. +		for( i = count-1; i >= 0; i--) { //going backward to avoid shifting
  1738. +			channel_clean(sd->channels[i],sd,0);
  1739. +		}
  1740. +	}
  1741. +}
  1742. +
  1743. +/*
  1744. + * Format *msg from *sd to send it in *channel
  1745. + * Also truncate extra char if msg too long (max=RACHSYS_MSG_LENGTH)
  1746. + */
  1747. +void channel_send(struct Channel *channel, struct map_session_data *sd, char *msg) {
  1748. +	char message[CHAN_MSG_LENGTH];
  1749. +	snprintf(message, CHAN_MSG_LENGTH, "[ #%s ] %s : %s",channel->name,sd->status.name, msg);
  1750. +	clif_channel_msg(channel,sd,message);
  1751. +}
  1752. +
  1753. +/*
  1754. + * Chk parameter for channel creation
  1755. + * @type (bitflag)
  1756. + *	1 : check name # + lenght
  1757. + *	2 : check if already exist, need 1
  1758. + *	4 : check pass lenght
  1759. + * return
  1760. + *  0 : success
  1761. + *  -1 : bad chan name
  1762. + *  -2 : bad chan name lenght
  1763. + *  -3 : pass given too long
  1764. + *  -4 : chan already exist
  1765. + */
  1766. +int channel_chk(char *chname, char *chpass, int type){
  1767. +	if(type&1){ //check name
  1768. +		if( chname[0] != '#' ) 	return -1; // Channel name must start with '#'
  1769. +		if ( strlen(chname) < 3 || strlen(chname) > CHAN_NAME_LENGTH )
  1770. +			return -2; // Channel length must be between 3 and %d.
  1771. +		if( (type&2) && (
  1772. +			strcmpi(chname + 1,Channel_Config.map_chname) == 0
  1773. +			|| strcmpi(chname + 1,Channel_Config.ally_chname) == 0
  1774. +			|| strdb_exists(channel_db, chname + 1) )
  1775. +			) {
  1776. +			return -4; // Channel '%s' already exist
  1777. +		}
  1778. +	}
  1779. +	if (type&4 && (chpass != '\0' && strlen(chpass) > CHAN_NAME_LENGTH ) ) {
  1780. +		return -3; // Channel pass can't be higher then %d.
  1781. +	}
  1782. +
  1783. +	return 0;
  1784. +}
  1785. +
  1786. +struct Channel* channel_name2channel(char *chname){
  1787. +	struct Channel *channel;
  1788. +	if(channel_chk(chname, NULL, 1)) return NULL;
  1789. +	if( !(channel = strdb_get(channel_db, chname + 1)) ) {
  1790. +		return NULL;
  1791. +	}
  1792. +	return channel;
  1793. +}
  1794. +
  1795. +int channel_haspc(struct Channel *channel,struct map_session_data *sd){
  1796. +	if(!channel || !sd) return 0;
  1797. +	return (idb_exists(channel->users, sd->status.char_id))?1:0;
  1798. +}
  1799. +
  1800. +int channel_pc_haschan(struct map_session_data *sd, struct Channel *channel){
  1801. +	int k;
  1802. +	if(!channel || !sd) return -2; //channel or player doesn't exist
  1803. +	ARR_FIND(0, sd->channel_count, k, strcmpi(channel->name,sd->channels[k]->name) == 0);
  1804. +	if( k >= sd->channel_count ) return -1;
  1805. +	return k;
  1806. +}
  1807. +
  1808. +int channel_display_list(struct map_session_data *sd, char *options){
  1809. +	struct Channel *channel;
  1810. +	char output[128];
  1811. +	int k;
  1812. +
  1813. +	if(!sd || !options)
  1814. +		return 0;
  1815. +
  1816. +	//display availaible colors
  1817. +	if( options[0] != '\0' && strcmpi(options,"colors") == 0 ) {
  1818. +		char msg[40];
  1819. +		for( k = 0; k < Channel_Config.colors_count; k++ ) {
  1820. +			sprintf(msg, "[ Channel list colors ] : %s",Channel_Config.colors_name[k]);
  1821. +			clif_colormes(sd, k, msg);
  1822. +		}
  1823. +	}
  1824. +	else if( options[0] != '\0' && strcmpi(options,"mine") == 0 ) { //display chan I'm into
  1825. +		clif_displaymessage(sd->fd, " ---- Joined Channels ----"); // ---- Joined Channels ----
  1826. +		if(!sd->channel_count)
  1827. +			clif_displaymessage(sd->fd, "You have not joined any channel yet");
  1828. +		else {
  1829. +			for(k=0; k<sd->channel_count; k++){
  1830. +				channel = sd->channels[k];
  1831. +				sprintf(output, msg_txt(sd,1409), channel->name, db_size(channel->users));// - #%s (%d users)
  1832. +				clif_displaymessage(sd->fd, output);
  1833. +			}
  1834. +		}
  1835. +	}
  1836. +	else { //display public chanels
  1837. +		DBIterator *iter;
  1838. +		bool show_all = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ? true : false;
  1839. +		clif_displaymessage(sd->fd, msg_txt(sd,1410)); // ---- Public Channels ----
  1840. +		if( Channel_Config.map_enable ) {
  1841. +			sprintf(output, msg_txt(sd,1409), Channel_Config.map_chname, map[sd->bl.m].channel ? db_size(map[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
  1842. +			clif_displaymessage(sd->fd, output);
  1843. +		}
  1844. +		if( Channel_Config.ally_enable && sd->status.guild_id ) {
  1845. +			struct guild *g = sd->guild;
  1846. +			if( !g ) return -1; //how can this happen if status.guild_id true ?
  1847. +			sprintf(output, msg_txt(sd,1409), Channel_Config.ally_chname, db_size(((struct Channel *)g->channel)->users));// - #%s ( %d users )
  1848. +			clif_displaymessage(sd->fd, output);
  1849. +		}
  1850. +		iter = db_iterator(channel_db);
  1851. +		for(channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) {
  1852. +			if( show_all || channel->type == CHAN_TYPE_PUBLIC ) {
  1853. +				sprintf(output, msg_txt(sd,1409), channel->name, db_size(channel->users));// - #%s (%d users)
  1854. +				clif_displaymessage(sd->fd, output);
  1855. +			}
  1856. +		}
  1857. +		dbi_destroy(iter);
  1858. +	}
  1859. +	return 0;
  1860. +}
  1861. +
  1862. +
  1863. +
  1864. +int channel_pccreate(struct map_session_data *sd, char *chname, char *chpass){
  1865. +	struct Channel *channel;
  1866. +	char output[128];
  1867. +	int8 res;
  1868. +
  1869. +	if(!sd || !chname)
  1870. +		return 0;
  1871. +
  1872. +	res = channel_chk(chname,chpass,7);
  1873. +	if(res==0){ //succes
  1874. +		channel = channel_create(chname + 1,chpass,0,CHAN_TYPE_PRIVATE);
  1875. +		channel->owner = sd->status.char_id;
  1876. +		channel_join(channel,sd);
  1877. +		if( !( channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) ) {
  1878. +			sprintf(output, msg_txt(sd,1403),chname); // You're now in the '%s' channel.
  1879. +			clif_displaymessage(sd->fd, output);
  1880. +		}
  1881. +	} else { //failure display cause
  1882. +		switch(res){
  1883. +		case -1: sprintf(output, msg_txt(sd,1405), CHAN_NAME_LENGTH); break;// Channel name must start with '#'.
  1884. +		case -2: sprintf(output, msg_txt(sd,1406), CHAN_NAME_LENGTH); break;// Channel length must be between 3 and %d.
  1885. +		case -3: sprintf(output, msg_txt(sd,1436), CHAN_NAME_LENGTH); break;// Channel pass can't be higher then %d.
  1886. +		case -4: sprintf(output, msg_txt(sd,1407), chname);// Channel '%s' is not available.
  1887. +		}
  1888. +		clif_displaymessage(sd->fd, output);
  1889. +		return -1;
  1890. +	}
  1891. +	return 0;
  1892. +}
  1893. +
  1894. +int channel_pcdelete(struct map_session_data *sd, char *chname){
  1895. +	struct Channel *channel;
  1896. +	char output[128];
  1897. +
  1898. +	if(!sd || !chname) return 0;
  1899. +
  1900. +	if( channel_chk(chname,NULL,1) ) {
  1901. +		clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'.
  1902. +		return -1;
  1903. +	}
  1904. +	if(strcmpi(chname + 1,Channel_Config.map_chname) == 0) channel = map[sd->bl.m].channel;
  1905. +	else if((strcmpi(chname + 1,Channel_Config.ally_chname) == 0)
  1906. +		&& sd->guild) channel = sd->guild->channel;
  1907. +	else channel = channel_name2channel(chname);
  1908. +
  1909. +	if(!channel){
  1910. +		sprintf(output, "Channel %s doesn't exist",chname);// You're not part of the '%s' channel.
  1911. +		clif_displaymessage(sd->fd, output);
  1912. +		return -2; //channel doesn't exist or player don't have it
  1913. +	}
  1914. +	channel_delete(channel);
  1915. +
  1916. +	sprintf(output, "Channel %s deleted",chname); // You've left the '%s' channel.
  1917. +	clif_displaymessage(sd->fd, output);
  1918. +
  1919. +	return 0;
  1920. +}
  1921. +
  1922. +int channel_pcleave(struct map_session_data *sd, char *chname){
  1923. +	struct Channel *channel;
  1924. +	char output[128];
  1925. +
  1926. +	if(!sd || !chname)
  1927. +		return 0;
  1928. +
  1929. +	if( channel_chk(chname,NULL,1) ) {
  1930. +		clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'.
  1931. +		return -1;
  1932. +	}
  1933. +	if(strcmpi(chname + 1,Channel_Config.map_chname) == 0){
  1934. +		channel_pcquit(sd,4); //quit map chan
  1935. +		return 0;
  1936. +	}
  1937. +	else if((strcmpi(chname + 1,Channel_Config.ally_chname) == 0)
  1938. +		&& sd->guild) {
  1939. +		channel_pcquit(sd,3); //leave guild and ally chan
  1940. +		return 0;
  1941. +	}
  1942. +	else channel = channel_name2channel(chname);
  1943. +
  1944. +	if(channel_pc_haschan(sd,channel)<0){
  1945. +		sprintf(output, msg_txt(sd,1425),chname);// You're not part of the '%s' channel.
  1946. +		clif_displaymessage(sd->fd, output);
  1947. +		return -2; //channel doesn't exist or player don't have it
  1948. +	}
  1949. +
  1950. +	if( !Channel_Config.closing && (channel->opt & CHAN_OPT_ANNOUNCE_JOIN) ) {
  1951. +		char message[60];
  1952. +		sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
  1953. +		clif_channel_msg(channel,sd,message);
  1954. +	}
  1955. +	channel_clean(channel,sd,0);
  1956. +
  1957. +	sprintf(output, msg_txt(sd,1426),chname); // You've left the '%s' channel.
  1958. +	clif_displaymessage(sd->fd, output);
  1959. +	return 0;
  1960. +}
  1961. +
  1962. +int channel_pcjoin(struct map_session_data *sd, char *chname, char *pass){
  1963. +	struct Channel *channel;
  1964. +	char output[128];
  1965. +
  1966. +	if(!sd || !chname)
  1967. +		return 0;
  1968. +
  1969. +	if( channel_chk(chname,NULL,1) ) {
  1970. +		clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'.
  1971. +		return -1;
  1972. +	}
  1973. +
  1974. +	if(Channel_Config.map_enable
  1975. +			&& (strcmpi(chname + 1,Channel_Config.map_chname) == 0)) {
  1976. +			if( !map[sd->bl.m].channel ) {
  1977. +				channel_mjoin(sd);
  1978. +				return 0;
  1979. +			}
  1980. +			channel = map[sd->bl.m].channel;
  1981. +	}
  1982. +	else if(Channel_Config.ally_enable
  1983. +		&& (strcmpi(chname + 1,Channel_Config.ally_chname) == 0)
  1984. +		&& sd->guild) {
  1985. +		if(!sd->guild->channel) {
  1986. +			channel_gjoin(sd,3);
  1987. +			return 0;
  1988. +		}
  1989. +		channel = sd->guild->channel;
  1990. +	}
  1991. +	else channel = channel_name2channel(chname);
  1992. +
  1993. +	if(channel){
  1994. +		if(channel_haspc(channel,sd)) {
  1995. +			sprintf(output, msg_txt(sd,1434),chname); // You're already in the '%s' channel.
  1996. +			clif_displaymessage(sd->fd, output);
  1997. +			return -1;
  1998. +		}
  1999. +		else if( channel->pass[0] != '\0') { //chan has a pass
  2000. +			if(strcmp(channel->pass,pass) != 0){ //wrong pass entry
  2001. +				if( pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) {
  2002. +					sd->stealth = true;
  2003. +				} else {
  2004. +					sprintf(output, msg_txt(sd,1401),chname,"Join"); // '%s' Channel is password protected (usage: %s <#channel_name> <password>)
  2005. +					clif_displaymessage(sd->fd, output);
  2006. +					return -1;
  2007. +				}
  2008. +			}
  2009. +		}
  2010. +	}
  2011. +	else {
  2012. +		sprintf(output, msg_txt(sd,1400),chname,"Join"); // Unknown Channel '%s' (usage: %s <#channel_name>)
  2013. +		clif_displaymessage(sd->fd, output);
  2014. +		return -1;
  2015. +	}
  2016. +
  2017. +	if( !( channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) ) {
  2018. +		sprintf(output, msg_txt(sd,1403),chname); // You're now in the '%s' channel.
  2019. +		clif_displaymessage(sd->fd, output);
  2020. +	}
  2021. +
  2022. +	channel_join(channel,sd);
  2023. +
  2024. +	return 0;
  2025. +}
  2026. +
  2027. +int channel_pccolor(struct map_session_data *sd, char *chname, char *color){
  2028. +	struct Channel *channel;
  2029. +	char output[128];
  2030. +	int k;
  2031. +
  2032. +	if(!sd)
  2033. +		return 0;
  2034. +
  2035. +	if( channel_chk(chname,NULL,1) ) {
  2036. +		clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'.
  2037. +		return -1;
  2038. +	}
  2039. +	channel = channel_name2channel(chname); //only search those in db since map and ally ain't ours
  2040. +	if( !channel ) {
  2041. +		sprintf(output, msg_txt(sd,1407), chname);// Channel '%s' is not available.
  2042. +		clif_displaymessage(sd->fd, output);
  2043. +		return -1;
  2044. +	}
  2045. +
  2046. +	if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) {
  2047. +		sprintf(output, msg_txt(sd,1412), chname);// You're not the owner of channel '%s'.
  2048. +		clif_displaymessage(sd->fd, output);
  2049. +		return -1;
  2050. +	}
  2051. +
  2052. +	ARR_FIND(0,Channel_Config.colors_count,k,( strcmpi(color,Channel_Config.colors_name[k]) == 0 ) );
  2053. +	if( k >= Channel_Config.colors_count ) {
  2054. +		sprintf(output, msg_txt(sd,1411), color);// Unknown color '%s'.
  2055. +		clif_displaymessage(sd->fd, output);
  2056. +		return -1;
  2057. +	}
  2058. +	channel->color = k;
  2059. +	sprintf(output, msg_txt(sd,1413),chname,Channel_Config.colors_name[k]);// '%s' channel color updated to '%s'.
  2060. +	clif_displaymessage(sd->fd, output);
  2061. +	return 0;
  2062. +}
  2063. +
  2064. +int channel_pcbind(struct map_session_data *sd, char *chname){
  2065. +	struct Channel *channel;
  2066. +	char output[128];
  2067. +
  2068. +	if(!sd)
  2069. +		return 0;
  2070. +
  2071. +	if( channel_chk(chname,NULL,1) ) {
  2072. +		clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'.
  2073. +		return -1;
  2074. +	}
  2075. +	if(strcmpi(chname + 1,Channel_Config.map_chname) == 0) channel = map[sd->bl.m].channel;
  2076. +	else if((strcmpi(chname + 1,Channel_Config.ally_chname) == 0)
  2077. +		&& sd->guild) channel = sd->guild->channel;
  2078. +	else channel = channel_name2channel(chname);
  2079. +	if(channel_pc_haschan(sd,channel)<0){
  2080. +		sprintf(output, msg_txt(sd,1425),chname);// You're not part of the '%s' channel.
  2081. +		clif_displaymessage(sd->fd, output);
  2082. +		return -2; //channel doesn't exist or player don't have it
  2083. +	}
  2084. +	sd->gcbind = channel;
  2085. +	sprintf(output, msg_txt(sd,1431),chname); // Your global chat is now binded to the '%s' channel.
  2086. +	clif_displaymessage(sd->fd, output);
  2087. +	return 0;
  2088. +}
  2089. +
  2090. +int channel_pcunbind(struct map_session_data *sd){
  2091. +	char output[128];
  2092. +
  2093. +	if(!sd)
  2094. +		return 0;
  2095. +
  2096. +	if( sd->gcbind == NULL ) {
  2097. +		clif_displaymessage(sd->fd, msg_txt(sd,1432));// Your global chat is not binded to any channel.
  2098. +		return -1;
  2099. +	}
  2100. +	sprintf(output, msg_txt(sd,1433),sd->gcbind->name); // Your global chat is now unbinded from the '#%s' channel.
  2101. +	clif_displaymessage(sd->fd, output);
  2102. +	sd->gcbind = NULL;
  2103. +	return 0;
  2104. +}
  2105. +
  2106. +/*
  2107. + * Read and verify configuration in confif_filename
  2108. + * Assign table value with value
  2109. + */
  2110. +void channel_read_config(void) {
  2111. +	config_t channels_conf;
  2112. +	config_setting_t *chsys = NULL;
  2113. +	const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name
  2114. +
  2115. +	if (conf_read_file(&channels_conf, config_filename))
  2116. +		return;
  2117. +
  2118. +	chsys = config_lookup(&channels_conf, "chsys");
  2119. +
  2120. +	if (chsys != NULL) {
  2121. +		config_setting_t *settings = config_setting_get_elem(chsys, 0);
  2122. +		config_setting_t *channels;
  2123. +		config_setting_t *colors;
  2124. +		int i,k;
  2125. +		const char *map_chname, *ally_chname,*map_color, *ally_color;
  2126. +		int ally_enabled = 0, local_enabled = 0;
  2127. +		int local_autojoin = 0, ally_autojoin = 0;
  2128. +		int allow_user_channel_creation = 0;
  2129. +
  2130. +		if( !config_setting_lookup_string(settings, "map_local_channel_name", &map_chname) )
  2131. +			map_chname = "map";
  2132. +		safestrncpy(Channel_Config.map_chname, map_chname, CHAN_NAME_LENGTH);
  2133. +
  2134. +		if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_chname) )
  2135. +			ally_chname = "ally";
  2136. +		safestrncpy(Channel_Config.ally_chname, ally_chname, CHAN_NAME_LENGTH);
  2137. +
  2138. +		config_setting_lookup_bool(settings, "map_local_channel", &local_enabled);
  2139. +		config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
  2140. +
  2141. +		if( local_enabled )
  2142. +			Channel_Config.map_enable = true;
  2143. +		if( ally_enabled )
  2144. +			Channel_Config.ally_enable = true;
  2145. +
  2146. +		config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
  2147. +		config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
  2148. +
  2149. +		if( local_autojoin )
  2150. +			Channel_Config.map_autojoin = true;
  2151. +		if( ally_autojoin )
  2152. +			Channel_Config.ally_autojoin = true;
  2153. +
  2154. +		config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
  2155. +
  2156. +		if( allow_user_channel_creation )
  2157. +			Channel_Config.user_chenable = true;
  2158. +
  2159. +		if( (colors = config_setting_get_member(settings, "colors")) != NULL ) {
  2160. +			int color_count = config_setting_length(colors);
  2161. +			CREATE( Channel_Config.colors, unsigned long, color_count );
  2162. +			CREATE( Channel_Config.colors_name, char *, color_count );
  2163. +			for(i = 0; i < color_count; i++) {
  2164. +				config_setting_t *color = config_setting_get_elem(colors, i);
  2165. +				CREATE( Channel_Config.colors_name[i], char, CHAN_NAME_LENGTH );
  2166. +
  2167. +				safestrncpy(Channel_Config.colors_name[i], config_setting_name(color), CHAN_NAME_LENGTH);
  2168. +				Channel_Config.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0);
  2169. +				Channel_Config.colors[i] = (Channel_Config.colors[i] & 0x0000FF) << 16 | (Channel_Config.colors[i] & 0x00FF00) | (Channel_Config.colors[i] & 0xFF0000) >> 16;//RGB to BGR
  2170. +			}
  2171. +			Channel_Config.colors_count = color_count;
  2172. +		}
  2173. +
  2174. +		config_setting_lookup_string(settings, "map_local_channel_color", &map_color);
  2175. +
  2176. +		for (k = 0; k < Channel_Config.colors_count; k++) {
  2177. +			if( strcmpi(Channel_Config.colors_name[k],map_color) == 0 )
  2178. +				break;
  2179. +		}
  2180. +
  2181. +		if( k < Channel_Config.colors_count ) {
  2182. +			Channel_Config.map_chcolor = k;
  2183. +		} else {
  2184. +			ShowError("channels.conf: unknown color '%s' for channel 'map_local_channel_color', disabling '#%s'...\n",map_color,map_chname);
  2185. +			Channel_Config.map_enable = false;
  2186. +		}
  2187. +
  2188. +		config_setting_lookup_string(settings, "ally_channel_color", &ally_color);
  2189. +
  2190. +		for (k = 0; k < Channel_Config.colors_count; k++) {
  2191. +			if( strcmpi(Channel_Config.colors_name[k],ally_color) == 0 )
  2192. +				break;
  2193. +		}
  2194. +
  2195. +		if( k < Channel_Config.colors_count ) {
  2196. +			Channel_Config.ally_chcolor = k;
  2197. +		} else {
  2198. +			ShowError("channels.conf: unknown color '%s' for channel 'ally_channel_color', disabling '#%s'...\n",map_color,ally_chname);
  2199. +			Channel_Config.ally_enable = false;
  2200. +		}
  2201. +
  2202. +		if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) {
  2203. +			int channel_count = config_setting_length(channels);
  2204. +
  2205. +			for(i = 0; i < channel_count; i++) {
  2206. +				config_setting_t *channel = config_setting_get_elem(channels, i);
  2207. +				const char *color = config_setting_get_string_elem(channels,i);
  2208. +				char *name = config_setting_name(channel);
  2209. +				struct Channel *chd;
  2210. +
  2211. +				for (k = 0; k < Channel_Config.colors_count; k++) {
  2212. +					if( strcmpi(Channel_Config.colors_name[k],color) == 0 )
  2213. +						break;
  2214. +				}
  2215. +				if( k == Channel_Config.colors_count ) {
  2216. +					ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name);
  2217. +					continue;
  2218. +				}
  2219. +				if( strcmpi(name,Channel_Config.map_chname) == 0 || strcmpi(name,Channel_Config.ally_chname) == 0 || strdb_exists(channel_db, name) ) {
  2220. +					ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name);
  2221. +					continue;
  2222. +				}
  2223. +				chd = channel_create(name,NULL,k,CHAN_TYPE_PUBLIC);
  2224. +			}
  2225. +		}
  2226. +
  2227. +		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel_db), config_filename);
  2228. +		config_destroy(&channels_conf);
  2229. +	}
  2230. +}
  2231. +
  2232. +/*
  2233. + * Initialise db and read config
  2234. + */
  2235. +int do_init_channel(void) {
  2236. +	channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, CHAN_NAME_LENGTH);
  2237. +	Channel_Config.ally_enable = Channel_Config.map_enable = Channel_Config.ally_autojoin = Channel_Config.map_autojoin = false;
  2238. +	channel_read_config();
  2239. +	return 0;
  2240. +}
  2241. +
  2242. +/*
  2243. + * Close all and cleanup
  2244. + * NB map and guild need to cleanup their chan as well
  2245. + */
  2246. +void do_final_channel(void) {
  2247. +	DBIterator *iter;
  2248. +	struct Channel *channel;
  2249. +	struct guild *g;
  2250. +	int i=0;
  2251. +
  2252. +	//delete all in remaining chan db
  2253. +	iter = db_iterator(channel_db);
  2254. +	for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) {
  2255. +		channel_delete(channel);
  2256. +	}
  2257. +	dbi_destroy(iter);
  2258. +	db_destroy(channel_db);
  2259. +
  2260. +	//delete all color thing
  2261. +	if( Channel_Config.colors_count ) {
  2262. +		for(i = 0; i < Channel_Config.colors_count; i++) {
  2263. +			aFree(Channel_Config.colors_name[i]);
  2264. +		}
  2265. +		aFree(Channel_Config.colors_name);
  2266. +		aFree(Channel_Config.colors);
  2267. +	}
  2268. +}
  2269. \ No newline at end of file
  2270. Index: src/map/channel.h
  2271. ===================================================================
  2272. --- src/map/channel.h	(revision 0)
  2273. +++ src/map/channel.h	(revision 0)
  2274. @@ -0,0 +1,88 @@
  2275. +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2276. +// For more information, see LICENCE in the main folder
  2277. +
  2278. +#ifndef CHANNEL_H
  2279. +#define	CHANNEL_H
  2280. +
  2281. +#include "pc.h"
  2282. +
  2283. +#ifdef	__cplusplus
  2284. +extern "C" {
  2285. +#endif
  2286. +
  2287. +#define CHAN_NAME_LENGTH 20
  2288. +#define CHAN_MSG_LENGTH 150
  2289. +
  2290. +enum Channel_Opt {
  2291. +	CHAN_OPT_BASE		= 0,
  2292. +	CHAN_OPT_ANNOUNCE_JOIN	= 1,	//display message when join or leave
  2293. +};
  2294. +
  2295. +enum Channel_Type {
  2296. +	CHAN_TYPE_PUBLIC	= 0,	//config file made
  2297. +	CHAN_TYPE_PRIVATE	= 1,	//user made
  2298. +	CHAN_TYPE_MAP		= 2,	//made by map
  2299. +	CHAN_TYPE_ALLY		= 3,	//guild
  2300. +};
  2301. +
  2302. +struct {
  2303. +	unsigned long *colors;		//color avail int list
  2304. +	char **colors_name;		//colors avail name list
  2305. +	unsigned char colors_count;	//color avail count
  2306. +	unsigned char map_chcolor, ally_chcolor; //msg color for map, ally
  2307. +	bool map_enable, ally_enable, user_chenable; //map, ally, users channels enable ?
  2308. +	bool map_autojoin, ally_autojoin;	//do user auto join in mapchange, guildjoin ?
  2309. +	char map_chname[CHAN_NAME_LENGTH], ally_chname[CHAN_NAME_LENGTH]; //channel name for map and ally
  2310. +	bool closing;			//server is closing
  2311. +} Channel_Config;
  2312. +
  2313. +struct Channel {
  2314. +	char name[CHAN_NAME_LENGTH];	//channel name
  2315. +	char pass[CHAN_NAME_LENGTH];	//channel password
  2316. +	unsigned char color;		//msg color
  2317. +	DBMap *users;			//user charid list
  2318. +	enum Channel_Opt opt;		//flag for some treatement
  2319. +	unsigned int owner;		//if private type charid of who create the chan,
  2320. +	enum Channel_Type type;		//type of channel
  2321. +	uint16 m;
  2322. +	int gid;			//if guild type guild_id
  2323. +};
  2324. +
  2325. +DBMap* channel_get_db(void);
  2326. +
  2327. +struct Channel* channel_create(char *name, char *pass, unsigned char color, enum Channel_Type chantype);
  2328. +void channel_delete(struct Channel *channel);
  2329. +
  2330. +void channel_join(struct Channel *channel, struct map_session_data *sd);
  2331. +void channel_mjoin(struct map_session_data *sd);
  2332. +void channel_gjoin(struct map_session_data *sd, int flag);
  2333. +void channel_ajoin(struct guild *g);
  2334. +void channel_clean(struct Channel *channel, struct map_session_data *sd, int flag);
  2335. +void channel_pcquit(struct map_session_data *sd, int type);
  2336. +
  2337. +void channel_send(struct Channel *channel, struct map_session_data *sd, char *msg);
  2338. +void channel_read_config(void);
  2339. +
  2340. +int channel_chk(char *name, char *pass, int type);
  2341. +struct Channel* channel_name2channel(char *name);
  2342. +int channel_haspc(struct Channel *channel,struct map_session_data *sd);
  2343. +int channel_pc_haschan(struct map_session_data *sd, struct Channel *channel);
  2344. +int channel_display_list(struct map_session_data *sd, char *option);
  2345. +
  2346. +int channel_pccreate(struct map_session_data *sd, char *name, char *pass);
  2347. +int channel_pcdelete(struct map_session_data *sd, char *chname);
  2348. +int channel_pcjoin(struct map_session_data *sd, char *chname, char *pass);
  2349. +int channel_pcleave(struct map_session_data *sd, char *chname);
  2350. +int channel_pccolor(struct map_session_data *sd, char *chname, char *color);
  2351. +int channel_pcbind(struct map_session_data *sd, char *chname);
  2352. +int channel_pcunbind(struct map_session_data *sd);
  2353. +
  2354. +int do_init_channel(void);
  2355. +void do_final_channel(void);
  2356. +
  2357. +#ifdef	__cplusplus
  2358. +}
  2359. +#endif
  2360. +
  2361. +#endif	/* CHANNEL_H */
  2362. +
Viewed 645 times, submitted by lighta.