www.pudn.com > 传奇3源代码.rar > char.c


// $Id: char2.c,v 1.4 2003/06/29 05:50:51 lemit Exp $ 
// original : char2.c 2003/03/14 11:58:35 Rev.1.5 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "core.h" 
#include "socket.h" 
#include "timer.h" 
#include "mmo.h" 
#include "version.h" 
#include "lock.h" 
#include "char.h" 
 
#include "inter.h" 
#include "int_pet.h" 
 
#ifdef MEMWATCH 
#include "memwatch.h" 
#endif 
 
struct mmo_map_server server[MAX_MAP_SERVERS]; 
int server_fd[MAX_MAP_SERVERS]; 
 
int login_fd; 
char userid[24]; 
char passwd[24]; 
char server_name[20]; 
char login_ip_str[16]; 
int login_ip; 
int login_port = 6900; 
char char_ip_str[16]; 
int char_ip; 
int char_port = 6121; 
int char_maintenance; 
int char_new; 
char char_txt[1024]; 
char unknown_char_name[1024]="Unknown"; 
char char_log_filename[1024]="log/char.log"; 
 
#define CHAR_STATE_WAITAUTH 0 
#define CHAR_STATE_AUTHOK 1 
struct char_session_data{ 
  int state; 
  int account_id,login_id1,login_id2,sex; 
  int found_char[9]; 
}; 
 
#define AUTH_FIFO_SIZE 256 
struct { 
  int account_id,char_id,login_id1,char_pos,delflag,sex; 
} auth_fifo[AUTH_FIFO_SIZE]; 
int auth_fifo_pos=0; 
 
int char_id_count=150000; 
struct mmo_charstatus *char_dat; 
int char_num,char_max; 
int max_connect_user=0; 
int autosave_interval=DEFAULT_AUTOSAVE_INTERVAL; 
int start_zeny = 500; 
 
// 弶婜埵抲乮conf僼傽僀儖偐傜嵞愝掕壜擻乯 
struct point start_point={"new_1-1.gat",53,111}; 
 
int mmo_char_tostr(char *str,struct mmo_charstatus *p) 
{ 
  int i; 
  char *str_p = str; 
  str_p += sprintf(str_p,"%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" 
	  "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" 
	  "\t%s,%d,%d\t%s,%d,%d\t", 
	  p->char_id,p->account_id,p->char_num,p->name, // 
	  p->class,p->base_level,p->job_level, 
	  p->base_exp,p->job_exp,p->zeny, 
	  p->hp,p->max_hp,p->sp,p->max_sp, 
	  p->str,p->agi,p->vit,p->int_,p->dex,p->luk, 
	  p->status_point,p->skill_point, 
	  p->option,p->karma,p->manner,	// 
	  p->party_id,p->guild_id,p->pet_id, 
	  p->hair,p->hair_color,p->clothes_color, 
	  p->weapon,p->shield,p->head_top,p->head_mid,p->head_bottom, 
	  p->last_point.map,p->last_point.x,p->last_point.y, // 
	  p->save_point.map,p->save_point.x,p->save_point.y 
	  ); 
  for(i=0;i<10;i++) 
    if(p->memo_point[i].map[0]){ 
      str_p += sprintf(str_p,"%s,%d,%d",p->memo_point[i].map,p->memo_point[i].x,p->memo_point[i].y); 
    } 
   
  *(str_p++)='\t'; 
  for(i=0;iinventory[i].nameid){ 
      str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", 
	      p->inventory[i].id,p->inventory[i].nameid,p->inventory[i].amount,p->inventory[i].equip, 
	      p->inventory[i].identify,p->inventory[i].refine,p->inventory[i].attribute, 
	      p->inventory[i].card[0],p->inventory[i].card[1],p->inventory[i].card[2],p->inventory[i].card[3]); 
    } 
  *(str_p++)='\t'; 
  for(i=0;icart[i].nameid){ 
      str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", 
	      p->cart[i].id,p->cart[i].nameid,p->cart[i].amount,p->cart[i].equip, 
	      p->cart[i].identify,p->cart[i].refine,p->cart[i].attribute, 
	      p->cart[i].card[0],p->cart[i].card[1],p->cart[i].card[2],p->cart[i].card[3]); 
    } 
  *(str_p++)='\t'; 
  for(i=0;iskill[i].id && p->skill[i].flag!=1){ 
      str_p += sprintf(str_p,"%d,%d ",p->skill[i].id,(p->skill[i].flag==0)?p->skill[i].lv:p->skill[i].flag-2); 
    } 
  *(str_p++)='\t'; 
  for(i=0;iglobal_reg_num;i++) 
    str_p += sprintf(str_p,"%s,%d ",p->global_reg[i].str,p->global_reg[i].value); 
  *(str_p++)='\t'; 
 
  *str_p='\0'; 
  return 0; 
} 
 
/* 
int mmo_char_tostr(char *str,struct mmo_charstatus *p) 
{ 
  int i; 
  sprintf(str,"%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" 
	  "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" 
	  "\t%s,%d,%d\t%s,%d,%d", 
	  p->char_id,p->account_id,p->char_num,p->name, // 
	  p->class,p->base_level,p->job_level, 
	  p->base_exp,p->job_exp,p->zeny, 
	  p->hp,p->max_hp,p->sp,p->max_sp, 
	  p->str,p->agi,p->vit,p->int_,p->dex,p->luk, 
	  p->status_point,p->skill_point, 
	  p->option,p->karma,p->manner,	// 
	  p->party_id,p->guild_id,p->pet_id, 
	  p->hair,p->hair_color,p->clothes_color, 
	  p->weapon,p->shield,p->head_top,p->head_mid,p->head_bottom, 
	  p->last_point.map,p->last_point.x,p->last_point.y, // 
	  p->save_point.map,p->save_point.x,p->save_point.y 
	  ); 
  strcat(str,"\t"); 
  for(i=0;i<10;i++) 
    if(p->memo_point[i].map[0]){ 
      sprintf(str+strlen(str),"%s,%d,%d",p->memo_point[i].map,p->memo_point[i].x,p->memo_point[i].y); 
    }       
  strcat(str,"\t"); 
  for(i=0;iinventory[i].nameid){ 
      sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", 
	      p->inventory[i].id,p->inventory[i].nameid,p->inventory[i].amount,p->inventory[i].equip, 
	      p->inventory[i].identify,p->inventory[i].refine,p->inventory[i].attribute, 
	      p->inventory[i].card[0],p->inventory[i].card[1],p->inventory[i].card[2],p->inventory[i].card[3]); 
    }       
  strcat(str,"\t"); 
  for(i=0;icart[i].nameid){ 
      sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ", 
	      p->cart[i].id,p->cart[i].nameid,p->cart[i].amount,p->cart[i].equip, 
	      p->cart[i].identify,p->cart[i].refine,p->cart[i].attribute, 
	      p->cart[i].card[0],p->cart[i].card[1],p->cart[i].card[2],p->cart[i].card[3]); 
    }       
  strcat(str,"\t"); 
  for(i=0;iskill[i].id && p->skill[i].flag!=1){ 
      sprintf(str+strlen(str),"%d,%d ",p->skill[i].id,(p->skill[i].flag==0)?p->skill[i].lv:p->skill[i].flag-2); 
    }       
  strcat(str,"\t"); 
  for(i=0;iglobal_reg_num;i++) 
    sprintf(str+strlen(str),"%s,%d ",p->global_reg[i].str,p->global_reg[i].value); 
  strcat(str,"\t"); 
  return 0; 
} 
*/ 
int mmo_char_fromstr(char *str,struct mmo_charstatus *p) 
{ 
  int tmp_int[256]; 
  int set,next,len,i; 
 
	// 384埲崀偺宍幃撉傒崬傒 
  if( (set=sscanf(str,"%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" 
		   "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" 
		   "\t%[^,],%d,%d\t%[^,],%d,%d%n", 
		   &tmp_int[0],&tmp_int[1],&tmp_int[2],p->name, // 
		   &tmp_int[3],&tmp_int[4],&tmp_int[5], 
		   &tmp_int[6],&tmp_int[7],&tmp_int[8], 
		   &tmp_int[9],&tmp_int[10],&tmp_int[11],&tmp_int[12], 
		   &tmp_int[13],&tmp_int[14],&tmp_int[15],&tmp_int[16],&tmp_int[17],&tmp_int[18], 
		   &tmp_int[19],&tmp_int[20], 
		   &tmp_int[21],&tmp_int[22],&tmp_int[23], // 
		   &tmp_int[24],&tmp_int[25],&tmp_int[26], 
		   &tmp_int[27],&tmp_int[28],&tmp_int[29], 
		   &tmp_int[30],&tmp_int[31],&tmp_int[32],&tmp_int[33],&tmp_int[34], 
		   p->last_point.map,&tmp_int[35],&tmp_int[36], // 
		   p->save_point.map,&tmp_int[37],&tmp_int[38],&next 
		 ) 
	)!=42 ){ 
		 	// 384埲慜偺宍幃偺撉傒崬傒 
	tmp_int[26]=0; 
	set=sscanf(str,"%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" 
		   "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" 
		   "\t%[^,],%d,%d\t%[^,],%d,%d%n", 
		   &tmp_int[0],&tmp_int[1],&tmp_int[2],p->name, // 
		   &tmp_int[3],&tmp_int[4],&tmp_int[5], 
		   &tmp_int[6],&tmp_int[7],&tmp_int[8], 
		   &tmp_int[9],&tmp_int[10],&tmp_int[11],&tmp_int[12], 
		   &tmp_int[13],&tmp_int[14],&tmp_int[15],&tmp_int[16],&tmp_int[17],&tmp_int[18], 
		   &tmp_int[19],&tmp_int[20], 
		   &tmp_int[21],&tmp_int[22],&tmp_int[23], // 
		   &tmp_int[24],&tmp_int[25],// 
		   &tmp_int[27],&tmp_int[28],&tmp_int[29], 
		   &tmp_int[30],&tmp_int[31],&tmp_int[32],&tmp_int[33],&tmp_int[34], 
		   p->last_point.map,&tmp_int[35],&tmp_int[36], // 
		   p->save_point.map,&tmp_int[37],&tmp_int[38],&next); 
	set++; 
  } 
  p->char_id=tmp_int[0]; 
  p->account_id=tmp_int[1]; 
  p->char_num=tmp_int[2]; 
  p->class=tmp_int[3]; 
  p->base_level=tmp_int[4]; 
  p->job_level=tmp_int[5]; 
  p->base_exp=tmp_int[6]; 
  p->job_exp=tmp_int[7]; 
  p->zeny=tmp_int[8]; 
  p->hp=tmp_int[9]; 
  p->max_hp=tmp_int[10]; 
  p->sp=tmp_int[11]; 
  p->max_sp=tmp_int[12]; 
  p->str=tmp_int[13]; 
  p->agi=tmp_int[14]; 
  p->vit=tmp_int[15]; 
  p->int_=tmp_int[16]; 
  p->dex=tmp_int[17]; 
  p->luk=tmp_int[18]; 
  p->status_point=tmp_int[19]; 
  p->skill_point=tmp_int[20]; 
  p->option=tmp_int[21]; 
  p->karma=tmp_int[22]; 
  p->manner=tmp_int[23]; 
  p->party_id=tmp_int[24]; 
  p->guild_id=tmp_int[25]; 
	p->pet_id=tmp_int[26]; 
  p->hair=tmp_int[27]; 
  p->hair_color=tmp_int[28]; 
  p->clothes_color=tmp_int[29]; 
  p->weapon=tmp_int[30]; 
  p->shield=tmp_int[31]; 
  p->head_top=tmp_int[32]; 
  p->head_mid=tmp_int[33]; 
  p->head_bottom=tmp_int[34]; 
  p->last_point.x=tmp_int[35]; 
  p->last_point.y=tmp_int[36]; 
  p->save_point.x=tmp_int[37]; 
  p->save_point.y=tmp_int[38]; 
  if(set!=42) 
    return 0; 
  if(str[next]=='\n' || str[next]=='\r') 
    return 1;	// 怴婯僨乕僞 
  next++; 
  for(i=0;str[next] && str[next]!='\t';i++){ 
    set=sscanf(str+next,"%[^,],%d,%d%n",p->memo_point[i].map,&tmp_int[0],&tmp_int[1],&len); 
    if(set!=3)  
      return 0; 
    p->memo_point[i].x=tmp_int[0]; 
    p->memo_point[i].y=tmp_int[1]; 
    next+=len; 
    if(str[next]==' ') 
      next++; 
  } 
  next++; 
  for(i=0;str[next] && str[next]!='\t';i++){ 
    set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", 
	       &tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3], 
	       &tmp_int[4],&tmp_int[5],&tmp_int[6], 
	       &tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len); 
    if(set!=11) 
      return 0; 
    p->inventory[i].id=tmp_int[0]; 
    p->inventory[i].nameid=tmp_int[1]; 
    p->inventory[i].amount=tmp_int[2]; 
    p->inventory[i].equip=tmp_int[3]; 
    p->inventory[i].identify=tmp_int[4]; 
    p->inventory[i].refine=tmp_int[5]; 
    p->inventory[i].attribute=tmp_int[6]; 
    p->inventory[i].card[0]=tmp_int[7]; 
    p->inventory[i].card[1]=tmp_int[8]; 
    p->inventory[i].card[2]=tmp_int[9]; 
    p->inventory[i].card[3]=tmp_int[10]; 
    next+=len; 
    if(str[next]==' ') 
      next++; 
  } 
  next++; 
  for(i=0;str[next] && str[next]!='\t';i++){ 
    set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n", 
	       &tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3], 
	       &tmp_int[4],&tmp_int[5],&tmp_int[6], 
	       &tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len); 
    if(set!=11) 
      return 0; 
    p->cart[i].id=tmp_int[0]; 
    p->cart[i].nameid=tmp_int[1]; 
    p->cart[i].amount=tmp_int[2]; 
    p->cart[i].equip=tmp_int[3]; 
    p->cart[i].identify=tmp_int[4]; 
    p->cart[i].refine=tmp_int[5]; 
    p->cart[i].attribute=tmp_int[6]; 
    p->cart[i].card[0]=tmp_int[7]; 
    p->cart[i].card[1]=tmp_int[8]; 
    p->cart[i].card[2]=tmp_int[9]; 
    p->cart[i].card[3]=tmp_int[10]; 
    next+=len; 
    if(str[next]==' ') 
      next++; 
  } 
  next++; 
  for(i=0;str[next] && str[next]!='\t';i++){ 
    set=sscanf(str+next,"%d,%d%n", 
	       &tmp_int[0],&tmp_int[1],&len); 
    if(set!=2) 
      return 0; 
    p->skill[tmp_int[0]].id=tmp_int[0]; 
    p->skill[tmp_int[0]].lv=tmp_int[1]; 
    next+=len; 
    if(str[next]==' ') 
      next++; 
  } 
  next++; 
  for(i=0;str[next] && str[next]!='\t' && str[next]!='\n' && str[next]!='\r';i++){ //global_reg幚憰埲慜偺athena.txt屳姺偺偨傔堦墳'\n'僠僃僢僋 
    set=sscanf(str+next,"%[^,],%d%n", 
	       p->global_reg[i].str,&p->global_reg[i].value,&len); 
    if(set!=2) 
      return 0; 
    next+=len; 
    if(str[next]==' ') 
      next++; 
  } 
  p->global_reg_num=i; 
  return 1; 
} 
 
int mmo_char_init(void) 
{ 
	char line[65536]; 
	int ret; 
	FILE *fp; 
	 
	fp=fopen(char_txt,"r"); 
	char_dat=calloc(sizeof(char_dat[0])*256, 1); 
	if (!char_dat) { 
		printf("out of memory: mmo_char_init\n"); 
		exit(1); 
	} 
	char_max=256; 
	if(fp==NULL) 
		return 0; 
	while(fgets(line,65535,fp)){ 
		if(char_num>=char_max){ 
			char_max+=256; 
			char_dat=realloc(char_dat,sizeof(char_dat[0])*char_max); 
			if (!char_dat) { 
				printf("out of memory: mmo_char_init\n"); 
				exit(1); 
			} 
			memset(char_dat + (char_max - 256), '\0', 
				256 * sizeof(*char_dat)); 
    	} 
		memset(&char_dat[char_num],0,sizeof(char_dat[0])); 
		ret=mmo_char_fromstr(line,&char_dat[char_num]); 
		if(ret){ 
			if(char_dat[char_num].char_id>=char_id_count) 
				char_id_count=char_dat[char_num].char_id+1; 
			char_num++; 
		} 
	} 
	fclose(fp); 
	return 0; 
} 
 
void mmo_char_sync(void) 
{ 
  char line[65536]; 
  int i,lock; 
  FILE *fp; 
 
  fp=lock_fopen(char_txt,&lock); 
  if(fp==NULL) 
    return; 
  for(i=0;i5*6 || 
		 dat[30]>=9 || 
		 dat[33]==0 || dat[33]>=20 || 
		 dat[31]>=9){ 
		logfp=fopen(char_log_filename,"a"); 
		if(logfp){ 
			fprintf(logfp,"make new char error %d-%d %s %d,%d,%d,%d,%d,%d %d,%d" RETCODE, 
				fd,dat[30],dat,dat[24],dat[25],dat[26],dat[27],dat[28],dat[29],dat[33],dat[31]); 
			fclose(logfp); 
		} 
		return -1; 
	} 
	logfp=fopen(char_log_filename,"a"); 
	if(logfp){ 
		fprintf(logfp,"make new char %d-%d %s" RETCODE,fd,dat[30],dat); 
		fclose(logfp); 
	} 
	sd=session[fd]->session_data; 
	 
	for(i=0;iaccount_id && char_dat[i].char_num==dat[30])) 
			break; 
	} 
	if(i!=char_num) 
		return -1; 
	if(char_num>=char_max){ 
		char_max+=256; 
		char_dat=realloc(char_dat,sizeof(char_dat[0])*char_max); 
		if (!char_dat) { 
			printf("out of memory: make_new_char\n"); 
			exit(1); 
		} 
		memset(char_dat + (char_max - 256), '\0', 256 * sizeof(*char_dat)); 
	} 
	memset(&char_dat[i],0,sizeof(char_dat[0])); 
	 
	char_dat[i].char_id=char_id_count++; 
	char_dat[i].account_id=sd->account_id; 
	char_dat[i].char_num=dat[30]; 
	strcpy(char_dat[i].name,dat); 
	char_dat[i].class=0; 
	char_dat[i].base_level=1; 
	char_dat[i].job_level=1; 
	char_dat[i].base_exp=0; 
	char_dat[i].job_exp=0; 
	char_dat[i].zeny=start_zeny; 
	char_dat[i].str=dat[24]; 
	char_dat[i].agi=dat[25]; 
	char_dat[i].vit=dat[26]; 
	char_dat[i].int_=dat[27]; 
	char_dat[i].dex=dat[28]; 
	char_dat[i].luk=dat[29]; 
	char_dat[i].max_hp=40 * (100 + char_dat[i].vit)/100; 
	char_dat[i].max_sp=11 * (100 + char_dat[i].int_)/100;; 
	char_dat[i].hp=char_dat[i].max_hp; 
	char_dat[i].sp=char_dat[i].max_sp; 
	char_dat[i].status_point=0; 
	char_dat[i].skill_point=0; 
	char_dat[i].option=0; 
	char_dat[i].karma=0; 
	char_dat[i].manner=0; 
	char_dat[i].party_id=0; 
	char_dat[i].guild_id=0; 
	char_dat[i].hair=dat[33]; 
	char_dat[i].hair_color=dat[31]; 
	char_dat[i].clothes_color=0; 
	char_dat[i].inventory[0].nameid = 1201; /* Knife */ 
	char_dat[i].inventory[0].amount = 1; 
	char_dat[i].inventory[0].equip = 0x02; 
	char_dat[i].inventory[0].identify = 1; 
	char_dat[i].inventory[1].nameid = 2301; /* Cotton Shirt */ 
	char_dat[i].inventory[1].amount = 1; 
	char_dat[i].inventory[1].equip = 0x10; 
	char_dat[i].inventory[1].identify = 1; 
	char_dat[i].weapon = 1; 
	char_dat[i].shield=0; 
	char_dat[i].head_top=0; 
	char_dat[i].head_mid=0; 
	char_dat[i].head_bottom=0; 
	memcpy(&char_dat[i].last_point,&start_point,sizeof(start_point)); 
	memcpy(&char_dat[i].save_point,&start_point,sizeof(start_point)); 
/*strcpy(char_dat[i].last_point.map,"new_1-1.gat"); 
	char_dat[i].last_point.x=start_po; 
	char_dat[i].last_point.y=111; 
	strcpy(char_dat[i].save_point.map,"new_1-1.gat"); 
	char_dat[i].save_point.x=53; 
	char_dat[i].save_point.y=111;*/ 
	char_num++; 
	 
	mmo_char_sync(); 
	return i; 
} 
 
int count_users(void) 
{ 
	if(login_fd>0 && session[login_fd]){ 
		int i,users; 
		for(i=0,users=0;i0){ 
				users+=server[i].users; 
			} 
		} 
		return users; 
	} 
  return 0; 
} 
 
int mmo_char_send006b(int fd,struct char_session_data *sd) 
{ 
  int i,j,found_num; 
#ifdef NEW_006b 
  int offset=24; 
#else 
  int offset=4; 
#endif 
 
  sd->state=CHAR_STATE_AUTHOK; 
  for(i=found_num=0;iaccount_id){ 
      sd->found_char[found_num]=i; 
      found_num++; 
      if(found_num==9) 
				break; 
    } 
  } 
  for(i=found_num;i<9;i++) 
    sd->found_char[i]=-1; 
 
	memset(WFIFOP(fd,0),0,offset+found_num*106); 
  WFIFOW(fd,0)=0x6b; 
  WFIFOW(fd,2)=offset+found_num*106; 
 
  for( i = 0; i < found_num; i++ ) { 
 
    j=sd->found_char[i]; 
 
    memset(WFIFOP(fd,offset+(i*106)),0x00,106); 
 
    WFIFOL(fd,offset+(i*106)) = char_dat[j].char_id; 
    WFIFOL(fd,offset+(i*106)+4) = char_dat[j].base_exp; 
    WFIFOL(fd,offset+(i*106)+8) = char_dat[j].zeny; 
    WFIFOL(fd,offset+(i*106)+12) = char_dat[j].job_exp; 
    WFIFOL(fd,offset+(i*106)+16) = char_dat[j].job_level; 
 
    WFIFOL(fd,offset+(i*106)+20) = 0; 
    WFIFOL(fd,offset+(i*106)+24) = 0; 
    WFIFOL(fd,offset+(i*106)+28) = char_dat[j].option; 
 
    WFIFOL(fd,offset+(i*106)+32) = char_dat[j].karma; 
    WFIFOL(fd,offset+(i*106)+36) = char_dat[j].manner; 
 
    WFIFOW(fd,offset+(i*106)+40) = char_dat[j].status_point; 
    WFIFOW(fd,offset+(i*106)+42) = (char_dat[j].hp > 0x7fff)? 0x7fff:char_dat[j].hp; 
    WFIFOW(fd,offset+(i*106)+44) = (char_dat[j].max_hp > 0x7fff)? 0x7fff:char_dat[j].max_hp; 
    WFIFOW(fd,offset+(i*106)+46) = (char_dat[j].sp > 0x7fff)? 0x7fff:char_dat[j].sp; 
    WFIFOW(fd,offset+(i*106)+48) = (char_dat[j].max_sp > 0x7fff)? 0x7fff:char_dat[j].max_sp; 
    WFIFOW(fd,offset+(i*106)+50) = DEFAULT_WALK_SPEED; // char_dat[j].speed; 
    WFIFOW(fd,offset+(i*106)+52) = char_dat[j].class; 
    WFIFOW(fd,offset+(i*106)+54) = char_dat[j].hair; 
    WFIFOW(fd,offset+(i*106)+56) = char_dat[j].weapon; 
    WFIFOW(fd,offset+(i*106)+58) = char_dat[j].base_level; 
    WFIFOW(fd,offset+(i*106)+60) = char_dat[j].skill_point; 
    WFIFOW(fd,offset+(i*106)+62) = char_dat[j].head_bottom; 
    WFIFOW(fd,offset+(i*106)+64) = char_dat[j].shield; 
    WFIFOW(fd,offset+(i*106)+66) = char_dat[j].head_top; 
    WFIFOW(fd,offset+(i*106)+68) = char_dat[j].head_mid; 
    WFIFOW(fd,offset+(i*106)+70) = char_dat[j].hair_color; 
    WFIFOW(fd,offset+(i*106)+72) = char_dat[j].clothes_color; 
 
    memcpy( WFIFOP(fd,offset+(i*106)+74), char_dat[j].name, 24 ); 
 
    WFIFOB(fd,offset+(i*106)+98) = (char_dat[j].str > 255)? 255:char_dat[j].str; 
    WFIFOB(fd,offset+(i*106)+99) = (char_dat[j].agi > 255)? 255:char_dat[j].agi; 
    WFIFOB(fd,offset+(i*106)+100) = (char_dat[j].vit > 255)? 255:char_dat[j].vit; 
    WFIFOB(fd,offset+(i*106)+101) = (char_dat[j].int_ > 255)? 255:char_dat[j].int_; 
    WFIFOB(fd,offset+(i*106)+102) = (char_dat[j].dex > 255)? 255:char_dat[j].dex; 
    WFIFOB(fd,offset+(i*106)+103) = (char_dat[j].luk > 255)? 255:char_dat[j].luk; 
    WFIFOB(fd,offset+(i*106)+104) = char_dat[j].char_num; 
  } 
 
  WFIFOSET(fd,WFIFOW(fd,2)); 
  return 0; 
} 
 
int set_account_reg2(int acc,int num,struct global_reg *reg) 
{ 
	int i,c; 
	for(i=0,c=0;ieof){ 
    if(fd==login_fd) 
      login_fd=-1; 
    close(fd); 
    delete_session(fd); 
    return 0; 
  } 
  printf("parse_tologin : %d %d %d\n",fd,RFIFOREST(fd),RFIFOW(fd,0)); 
  sd=session[fd]->session_data; 
  while(RFIFOREST(fd)>=2){ 
    switch(RFIFOW(fd,0)){ 
    case 0x2711: 
      if(RFIFOREST(fd)<3) 
	return 0; 
      if(RFIFOB(fd,2)){ 
	printf("connect login server error : %d\n",RFIFOB(fd,2)); 
	exit(1); 
      } 
      RFIFOSKIP(fd,3); 
      break; 
    case 0x2713: 
      if(RFIFOREST(fd)<7) 
	return 0; 
      for(i=0;isession_data)){ 
	  if(sd->account_id==RFIFOL(fd,2)) 
	    break; 
	} 
      } 
      fdc=i; 
      if(fdc==fd_max){ 
	RFIFOSKIP(fd,7); 
	break; 
      } 
printf("parse_tologin 2713 : %d\n",RFIFOB(fd,6)); 
      if(RFIFOB(fd,6)!=0){ 
	WFIFOW(fdc,0)=0x6c; 
	WFIFOB(fdc,2)=0x42; 
	WFIFOSET(fdc,3); 
	RFIFOSKIP(fd,7); 
	break; 
      } 
 
			if(max_connect_user > 0) { 
				if(count_users() < max_connect_user) 
					mmo_char_send006b(fdc,sd); 
				else { 
					WFIFOW(fdc,0)=0x6c; 
					WFIFOW(fdc,2)=0; 
					WFIFOSET(fdc,3); 
				} 
			} 
			else 
				mmo_char_send006b(fdc,sd); 
 
      RFIFOSKIP(fd,7); 
      break; 
	 
	case 0x2721:	// gm reply 
	  { 
	  	int oldacc,newacc; 
		unsigned char buf[64]; 
	  	if(RFIFOREST(fd)<10) 
			return 0; 
		oldacc=RFIFOL(fd,2); 
		newacc=RFIFOL(fd,6); 
		RFIFOSKIP(fd,10); 
		if(newacc>0){ 
			for(i=0;i map\n"); 
	  }break; 
 
	case 0x2723:	// changesex reply 
	  { 
	  	int acc,sex,i/*,h,j*/; 
		unsigned char buf[64]; 
	  	if(RFIFOREST(fd)<7) 
			return 0; 
 
		acc=RFIFOL(fd,2); 
		sex=RFIFOB(fd,6); 
		RFIFOSKIP(fd,7); 
		if(acc>0){ 
			for(i=0;i0 && !char_dat[i].skill[j].flag){ 
								char_dat[i].skill_point += char_dat[i].skill[j].lv; 
								char_dat[i].skill[j].lv = 0; 
							} 
						}*/ 
					} 
				} 
			} 
		} 
		WBUFW(buf,0)=0x2b0d; 
		WBUFL(buf,2)=acc; 
		WBUFB(buf,6)=sex; 
 
		mapif_sendall(buf,7); 
//		printf("char -> map\n"); 
	  }break; 
 
	// account_reg2曄峏捠抦 
	case 0x2729: { 
			struct global_reg reg[ACCOUNT_REG2_NUM]; 
			unsigned char buf[4096]; 
			int j,p,acc; 
			if(RFIFOREST(fd)<4) 
				return 0; 
			if(RFIFOREST(fd)eof=1; 
      return 0; 
    } 
  } 
  RFIFOFLUSH(fd); 
  return 0; 
} 
 
int parse_frommap(int fd) 
{ 
	int i,j; 
	int id; 
	 
	for(id=0;ideof=1; 
	if(session[fd]->eof){ 
		for(i=0;i=2){ 
		switch(RFIFOW(fd,0)){ 
		// 儅僢僾僒乕僶乕偐傜扴摉儅僢僾柤傪庴怣 
		case 0x2afa: 
			if(RFIFOREST(fd)<4 || RFIFOREST(fd)=0 && x!=id){ 
						WFIFOW(fd,0)=0x2b04; 
						WFIFOL(fd,4)=server[x].ip; 
						WFIFOW(fd,8)=server[x].port; 
						for(i=0,j=0;i0) 
								memcpy(WFIFOP(fd,12+(j++)*16),server[x].map[i],16); 
						} 
						if(j>0){ 
							WFIFOW(fd,10)=j; 
							WFIFOW(fd,2)=j*16+12; 
							WFIFOSET(fd,WFIFOW(fd,2)); 
						} 
					} 
				} 
			} 
			break; 
		// 擣徹梫媮 
		case 0x2afc: 
			if(RFIFOREST(fd)<14) 
				return 0; 
			printf("auth_fifo search %08x %08x %08x\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); 
			for(i=0;i=AUTH_FIFO_SIZE){ 
				auth_fifo_pos=0; 
			} 
			printf("auth_fifo set %d - %08x %08x\n",auth_fifo_pos,RFIFOL(fd,2),RFIFOL(fd,6)); 
			auth_fifo[auth_fifo_pos].account_id=RFIFOL(fd,2); 
			auth_fifo[auth_fifo_pos].char_id=0; 
			auth_fifo[auth_fifo_pos].login_id1=RFIFOL(fd,6); 
			auth_fifo[auth_fifo_pos].delflag=2; 
			auth_fifo[auth_fifo_pos].char_pos=0; 
			auth_fifo_pos++; 
			 
			WFIFOW(fd,0)=0x2b03; 
			WFIFOL(fd,2)=RFIFOL(fd,2); 
			WFIFOB(fd,6)=0; 
			WFIFOSET(fd,7); 
			 
			RFIFOSKIP(fd,10); 
			 
			break; 
		// 儅僢僾僒乕僶乕娫堏摦梫媮 
		case 0x2b05: 
			if(RFIFOREST(fd)<41) 
				return 0; 
 
			if(auth_fifo_pos>=AUTH_FIFO_SIZE){ 
				auth_fifo_pos=0; 
			} 
			memcpy(WFIFOP(fd,2),RFIFOP(fd,2),38); 
			WFIFOW(fd,0)=0x2b06; 
 
			printf("auth_fifo set %d - %08x %08x\n",auth_fifo_pos,RFIFOL(fd,2),RFIFOL(fd,6)); 
			auth_fifo[auth_fifo_pos].account_id=RFIFOL(fd,2); 
			auth_fifo[auth_fifo_pos].char_id=RFIFOL(fd,10); 
			auth_fifo[auth_fifo_pos].login_id1=RFIFOL(fd,6); 
			auth_fifo[auth_fifo_pos].delflag=0; 
			auth_fifo[auth_fifo_pos].sex=RFIFOB(fd,40); 
			{ 
				int i=0; 
				for(i=0;i login %d %s %d\n",RFIFOL(fd,4),RFIFOP(fd,8),RFIFOW(fd,2)); 
			RFIFOSKIP(fd,RFIFOW(fd,2)); 
			break; 
 
		//惈暿曄姺梫媮 
		case 0x2b0c: 
			if(RFIFOREST(fd)<4) 
				return 0; 
			if(RFIFOREST(fd) length error : %d : %d\n",RFIFOREST(fd),RFIFOW(fd,2)); 
				return 0;} 
			WFIFOW(login_fd,0)=0x2722; 
			WFIFOW(login_fd,2)=RFIFOW(fd,2); 
			WFIFOL(login_fd,4)=RFIFOL(fd,4); 
			WFIFOB(login_fd,8)=RFIFOB(fd,8); 
			WFIFOSET(login_fd,RFIFOW(fd,2)); 
//			printf("char : change sex -> login %d %d %d \n",RFIFOL(fd,4),RFIFOB(fd,8),RFIFOW(fd,2)); 
			RFIFOSKIP(fd,RFIFOW(fd,2)); 
			break; 
 
		// account_reg曐懚梫媮 
		case 0x2b10: { 
			struct global_reg reg[ACCOUNT_REG2_NUM]; 
			int j,p,acc; 
			if(RFIFOREST(fd)<4) 
				return 0; 
			if(RFIFOREST(fd)eof=1;	 
			return 0; 
		} 
	} 
	return 0; 
} 
 
int search_mapserver(char *map) 
{ 
	int i,j,k; 
	printf("search_mapserver %s\n",map); 
	for(i=0;i %d\n",map,i); 
				return i; 
			} 
			//printf("%s : %s = %d\n",server[i].map[j],map,k); 
		} 
	} 
	printf("search_mapserver failed\n"); 
	return -1; 
} 
 
int char_mapif_init(int fd) 
{ 
	return inter_mapif_init(fd); 
} 
 
int parse_char(int fd) 
{ 
	int i,ch; 
	struct char_session_data *sd; 
 
	if(login_fd<0) 
		session[fd]->eof=1; 
	if(session[fd]->eof){ 
		if(fd==login_fd) 
			login_fd=-1; 
		close(fd); 
		delete_session(fd); 
		return 0; 
	} 
	if(RFIFOW(fd,0)<30000) 
		printf("parse_char : %d %d %d\n",fd,RFIFOREST(fd),RFIFOW(fd,0)); 
	sd=session[fd]->session_data; 
	while(RFIFOREST(fd)>=2){ 
		switch(RFIFOW(fd,0)){ 
		case 0x65:	// 愙懕梫媮 
			if(RFIFOREST(fd)<17) 
				return 0; 
			if(sd==NULL){ 
				sd=session[fd]->session_data=calloc(sizeof(*sd), 1); 
				memset(sd,0,sizeof(*sd)); 
			} 
			sd->account_id=RFIFOL(fd,2); 
			sd->login_id1=RFIFOL(fd,6); 
			sd->login_id2=RFIFOL(fd,10); 
			sd->sex=RFIFOB(fd,16); 
			sd->state=CHAR_STATE_WAITAUTH; 
 
			WFIFOL(fd,0)=RFIFOL(fd,2); 
			WFIFOSET(fd,4); 
 
			for(i=0;iaccount_id && 
				   auth_fifo[i].login_id1==sd->login_id1 && 
				   auth_fifo[i].delflag==2){ 
					auth_fifo[i].delflag=1; 
					break; 
				} 
			} 
			if(i==AUTH_FIFO_SIZE){ 
				WFIFOW(login_fd,0)=0x2712; 
				WFIFOL(login_fd,2)=sd->account_id; 
				WFIFOL(login_fd,6)=sd->login_id1; 
				WFIFOL(login_fd,10)=sd->login_id2; 
				WFIFOB(login_fd,14)=sd->sex; 
				WFIFOSET(login_fd,15); 
			} else { 
				if(max_connect_user > 0) { 
					if(count_users() < max_connect_user) 
						mmo_char_send006b(fd,sd); 
					else { 
						WFIFOW(fd,0)=0x6c; 
						WFIFOW(fd,2)=0; 
						WFIFOSET(fd,3); 
					} 
				} 
				else 
					mmo_char_send006b(fd,sd); 
			} 
 
			RFIFOSKIP(fd,17); 
			break; 
		case 0x66:	// 僉儍儔慖戰 
			if(RFIFOREST(fd)<3) 
				return 0; 
			for(ch=0;ch<9;ch++) 
				if(sd->found_char[ch]>=0 && char_dat[sd->found_char[ch]].char_num==RFIFOB(fd,2)) 
					break; 
			if(ch!=9){ 
				FILE *logfp; 
 
				logfp=fopen(char_log_filename,"a"); 
				if(logfp){ 
					fprintf(logfp,"char select %d-%d %s" RETCODE,sd->account_id,RFIFOB(fd,2),char_dat[sd->found_char[ch]].name); 
					fclose(logfp); 
				} 
 
				WFIFOW(fd,0)=0x71; 
				WFIFOL(fd,2)=char_dat[sd->found_char[ch]].char_id; 
				i=search_mapserver(char_dat[sd->found_char[ch]].last_point.map); 
				if(i<0){ 
					memcpy(char_dat[sd->found_char[ch]].last_point.map,"prontera.gat",16); 
					i=search_mapserver(char_dat[sd->found_char[ch]].last_point.map); 
					if(i<0) 
						i=0; 
				} 
				memcpy(WFIFOP(fd,6),char_dat[sd->found_char[ch]].last_point.map,16); 
				WFIFOL(fd,22)=server[i].ip; 
				WFIFOW(fd,26)=server[i].port; 
				WFIFOSET(fd,28); 
 
				if(auth_fifo_pos>=AUTH_FIFO_SIZE){ 
					auth_fifo_pos=0; 
				} 
				printf("auth_fifo set %d - %08x %08x %08x\n",auth_fifo_pos,sd->account_id,char_dat[sd->found_char[ch]].char_id,sd->login_id1); 
				auth_fifo[auth_fifo_pos].account_id=sd->account_id; 
				auth_fifo[auth_fifo_pos].char_id=char_dat[sd->found_char[ch]].char_id; 
				auth_fifo[auth_fifo_pos].login_id1=sd->login_id1; 
				auth_fifo[auth_fifo_pos].delflag=0; 
				auth_fifo[auth_fifo_pos].char_pos=sd->found_char[ch]; 
				auth_fifo[auth_fifo_pos].sex=sd->sex; 
				auth_fifo_pos++; 
			} 
			RFIFOSKIP(fd,3); 
			break; 
		case 0x67:	// 嶌惉 
			if(RFIFOREST(fd)<37) 
				return 0; 
			i=make_new_char(fd,RFIFOP(fd,2)); 
			if(i<0){ 
				WFIFOW(fd,0)=0x6e; 
				WFIFOB(fd,2)=0x00; 
				WFIFOSET(fd,3); 
				RFIFOSKIP(fd,37); 
				break; 
			} 
 
			WFIFOW(fd,0)=0x6d; 
			memset(WFIFOP(fd,2),0x00,106); 
 
			WFIFOL(fd,2) = char_dat[i].char_id; 
			WFIFOL(fd,2+4) = char_dat[i].base_exp; 
			WFIFOL(fd,2+8) = char_dat[i].zeny; 
			WFIFOL(fd,2+12) = char_dat[i].job_exp; 
			WFIFOL(fd,2+16) = char_dat[i].job_level; 
 
			WFIFOL(fd,2+28) = char_dat[i].karma; 
			WFIFOL(fd,2+32) = char_dat[i].manner; 
 
			WFIFOW(fd,2+40) = 0x30; 
			WFIFOW(fd,2+42) = (char_dat[i].hp > 0x7fff)? 0x7fff:char_dat[i].hp; 
			WFIFOW(fd,2+44) = (char_dat[i].max_hp > 0x7fff)? 0x7fff:char_dat[i].max_hp; 
			WFIFOW(fd,2+46) = (char_dat[i].sp > 0x7fff)? 0x7fff:char_dat[i].sp; 
			WFIFOW(fd,2+48) = (char_dat[i].max_sp > 0x7fff)? 0x7fff:char_dat[i].max_sp; 
			WFIFOW(fd,2+50) = DEFAULT_WALK_SPEED; // char_dat[i].speed; 
			WFIFOW(fd,2+52) = char_dat[i].class; 
			WFIFOW(fd,2+54) = char_dat[i].hair; 
 
			WFIFOW(fd,2+58) = char_dat[i].base_level; 
			WFIFOW(fd,2+60) = char_dat[i].skill_point; 
 
			WFIFOW(fd,2+64) = char_dat[i].shield; 
			WFIFOW(fd,2+66) = char_dat[i].head_top; 
			WFIFOW(fd,2+68) = char_dat[i].head_mid; 
			WFIFOW(fd,2+70) = char_dat[i].hair_color; 
 
			memcpy( WFIFOP(fd,2+74), char_dat[i].name, 24 ); 
 
			WFIFOB(fd,2+98) = (char_dat[i].str > 255)? 255:char_dat[i].str; 
			WFIFOB(fd,2+99) = (char_dat[i].agi > 255)? 255:char_dat[i].agi; 
			WFIFOB(fd,2+100) = (char_dat[i].vit > 255)? 255:char_dat[i].vit; 
			WFIFOB(fd,2+101) = (char_dat[i].int_ > 255)? 255:char_dat[i].int_; 
			WFIFOB(fd,2+102) = (char_dat[i].dex > 255)? 255:char_dat[i].dex; 
			WFIFOB(fd,2+103) = (char_dat[i].luk > 255)? 255:char_dat[i].luk; 
			WFIFOB(fd,2+104) = char_dat[i].char_num; 
 
			WFIFOSET(fd,108); 
			RFIFOSKIP(fd,37); 
			for(ch=0;ch<9;ch++) { 
				if(sd->found_char[ch]==-1) { 
					sd->found_char[ch]=i; 
					break; 
				} 
			} 
		case 0x68:	// 嶍彍 
			if(RFIFOREST(fd)<46) 
				return 0; 
			for(i=0;i<9;i++){ 
				if(char_dat[sd->found_char[i]].char_id==RFIFOL(fd,2)){ 
					int j; 
					if(char_dat[sd->found_char[i]].pet_id) 
						inter_pet_delete(char_dat[sd->found_char[i]].pet_id); 
					for(j=0;jfound_char[i]].inventory[j].card[0] == (short)0xff00) 
							inter_pet_delete(*((long *)(&char_dat[sd->found_char[i]].inventory[j].card[2]))); 
					for(j=0;jfound_char[i]].cart[j].card[0] == (short)0xff00) 
							inter_pet_delete(*((long *)(&char_dat[sd->found_char[i]].cart[j].card[2]))); 
					if(sd->found_char[i]!=char_num-1){ 
						memcpy(&char_dat[sd->found_char[i]],&char_dat[char_num-1],sizeof(char_dat[0])); 
					} 
					char_num--; 
					for(ch=i;ch<9-1;ch++) 
						sd->found_char[ch]=sd->found_char[ch+1]; 
					sd->found_char[8]=-1; 
					break; 
				} 
			} 
			if(i==9){ 
				WFIFOW(fd,0)=0x70; 
				WFIFOB(fd,2)=0; 
				WFIFOSET(fd,3); 
			} else { 
				WFIFOW(fd,0)=0x6f; 
				WFIFOSET(fd,2); 
			} 
			RFIFOSKIP(fd,46); 
			break; 
		case 0x2af8:	// 儅僢僾僒乕僶乕儘僌僀儞 
			if(RFIFOREST(fd)<60) 
				return 0; 
			WFIFOW(fd,0)=0x2af9; 
			for(i=0;ifunc_parse=parse_frommap; 
				server_fd[i]=fd; 
				server[i].ip=RFIFOL(fd,54); 
				server[i].port=RFIFOW(fd,58); 
				server[i].users=0; 
				memset(server[i].map,0,sizeof(server[i].map)); 
				WFIFOSET(fd,3); 
				RFIFOSKIP(fd,60); 
				realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);	 
				char_mapif_init(fd); 
				return 0; 
			} 
			break; 
		case 0x187:	// Alive怣崋丠 
			if (RFIFOREST(fd) < 6) { 
				return 0; 
			} 
			RFIFOSKIP(fd, 6); 
			break; 
		 
		case 0x7530:	// Athena忣曬強摼 
			WFIFOW(fd,0)=0x7531; 
			WFIFOB(fd,2)=ATHENA_MAJOR_VERSION; 
			WFIFOB(fd,3)=ATHENA_MINOR_VERSION; 
			WFIFOB(fd,4)=ATHENA_REVISION; 
			WFIFOB(fd,5)=ATHENA_RELEASE_FLAG; 
			WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG; 
			WFIFOB(fd,7)=ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR; 
			WFIFOW(fd,8)=ATHENA_MOD_VERSION; 
			WFIFOSET(fd,10); 
			RFIFOSKIP(fd,2); 
			return 0; 
		case 0x7532:	// 愙懕偺愗抐(default偲張棟偼堦弿偩偑柧帵揑偵偡傞偨傔) 
			close(fd); 
			session[fd]->eof=1; 
			return 0; 
 
		default: 
			close(fd); 
			session[fd]->eof=1; 
			return 0; 
		} 
	} 
	RFIFOFLUSH(fd); 
	return 0; 
} 
 
// 慡偰偺MAP僒乕僶乕偵僨乕僞憲怣乮憲怣偟偨map嶪偺悢傪曉偡乯 
int mapif_sendall(unsigned char *buf,unsigned int len) 
{ 
	int i,c; 
	for(i=0,c=0;i0){ 
			memcpy(WFIFOP(fd,0),buf,len); 
			WFIFOSET(fd,len); 
			c++; 
		} 
	} 
	return c; 
} 
// 帺暘埲奜偺慡偰偺MAP僒乕僶乕偵僨乕僞憲怣乮憲怣偟偨map嶪偺悢傪曉偡乯 
int mapif_sendallwos(int sfd,unsigned char *buf,unsigned int len) 
{ 
	int i,c; 
	for(i=0,c=0;i0 && fd!=sfd){ 
			memcpy(WFIFOP(fd,0),buf,len); 
			WFIFOSET(fd,len); 
			c++; 
		} 
	} 
	return c; 
} 
// MAP僒乕僶乕偵僨乕僞憲怣乮map嶪惗懚妋擣桳傝乯 
int mapif_send(int fd,unsigned char *buf,unsigned int len) 
{ 
	int i; 
	for(i=0;i0){ 
			memcpy(WFIFOP(fd,0),buf,len); 
			WFIFOSET(fd,len); 
			return 1; 
		} 
	} 
	return 0; 
} 
 
int send_users_tologin(int tid,unsigned int tick,int id,int data) 
{ 
  if(login_fd>0 && session[login_fd]){ 
    int i,users; 
    for(i=0,users=0;i0){ 
	users+=server[i].users; 
      } 
    } 
    WFIFOW(login_fd,0)=0x2714; 
    WFIFOL(login_fd,2)=users; 
    WFIFOSET(login_fd,6); 
    for(i=0;i0){ 
	WFIFOW(fd,0)=0x2b00; 
	WFIFOL(fd,2)=users; 
	WFIFOSET(fd,6); 
      } 
    } 
  } 
  return 0; 
} 
 
int check_connect_login_server(int tid,unsigned int tick,int id,int data) 
{ 
  if(login_fd<=0 || session[login_fd]==NULL){ 
    login_fd=make_connection(login_ip,login_port); 
    session[login_fd]->func_parse=parse_tologin; 
	realloc_fifo(login_fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);	 
    WFIFOW(login_fd,0)=0x2710; 
    memcpy(WFIFOP(login_fd,2),userid,24); 
    memcpy(WFIFOP(login_fd,26),passwd,24); 
    WFIFOL(login_fd,50)=0; 
    WFIFOL(login_fd,54)=char_ip; 
    WFIFOL(login_fd,58)=char_port; 
    memcpy(WFIFOP(login_fd,60),server_name,20); 
    WFIFOW(login_fd,82)=char_maintenance; 
    WFIFOW(login_fd,84)=char_new; 
    WFIFOSET(login_fd,86); 
  } 
  return 0; 
} 
 
int char_config_read(const char *cfgName) 
{ 
	struct hostent *h=NULL; 
	char line[1024],w1[1024],w2[1024]; 
	int i; 
	FILE *fp=fopen(cfgName,"r"); 
	if(fp==NULL){ 
		printf("file not found: %s\n",cfgName); 
		exit(1); 
	} 
 
	while(fgets(line,1020,fp)){ 
		if(line[0] == '/' && line[1] == '/') 
			continue; 
 
		i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); 
		if(i!=2) 
			continue; 
		if(strcmpi(w1,"userid")==0){ 
			memcpy(userid,w2,24); 
		} 
		else if(strcmpi(w1,"passwd")==0){ 
			memcpy(passwd,w2,24); 
		} 
		else if(strcmpi(w1,"server_name")==0){ 
			memcpy(server_name,w2,16); 
		} 
		else if(strcmpi(w1,"login_ip")==0){ 
			h = gethostbyname (w2); 
			if(h != NULL) {  
				printf("Login server IP address : %s -> %d.%d.%d.%d\n",w2,(unsigned char)h->h_addr[0],(unsigned char)h->h_addr[1],(unsigned char)h->h_addr[2],(unsigned char)h->h_addr[3]); 
				sprintf(login_ip_str,"%d.%d.%d.%d",(unsigned char)h->h_addr[0],(unsigned char)h->h_addr[1],(unsigned char)h->h_addr[2],(unsigned char)h->h_addr[3]); 
			} 
			else 
				memcpy(login_ip_str,w2,16); 
		} 
		else if(strcmpi(w1,"login_port")==0){ 
			login_port=atoi(w2); 
		} 
		else if(strcmpi(w1,"char_ip")==0){ 
			h = gethostbyname (w2); 
			if(h != NULL) {  
				printf("Character server IP address : %s -> %d.%d.%d.%d\n",w2,(unsigned char)h->h_addr[0],(unsigned char)h->h_addr[1],(unsigned char)h->h_addr[2],(unsigned char)h->h_addr[3]); 
				sprintf(char_ip_str,"%d.%d.%d.%d",(unsigned char)h->h_addr[0],(unsigned char)h->h_addr[1],(unsigned char)h->h_addr[2],(unsigned char)h->h_addr[3]); 
			} 
			else 
				memcpy(char_ip_str,w2,16); 
		} 
		else if(strcmpi(w1,"char_port")==0){ 
			char_port=atoi(w2); 
		} 
		else if(strcmpi(w1,"char_maintenance")==0){ 
			char_maintenance=atoi(w2); 
		} 
		else if(strcmpi(w1,"char_new")==0){ 
			char_new=atoi(w2); 
		} 
		else if(strcmpi(w1,"char_txt")==0){ 
			strcpy(char_txt,w2); 
		} 
		else if(strcmpi(w1,"max_connect_user")==0){ 
			max_connect_user=atoi(w2); 
		} 
		else if(strcmpi(w1,"autosave_time")==0){ 
			autosave_interval=atoi(w2)*1000; 
			if(autosave_interval <= 0) 
				autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; 
		} 
		else if(strcmpi(w1,"start_point")==0){ 
			char map[32]; 
			int x,y; 
			if( sscanf(w2,"%[^,],%d,%d",map,&x,&y)<3 ) 
				continue; 
			memcpy(start_point.map,map,16); 
			start_point.x=x; 
			start_point.y=y; 
		} 
		else if(strcmpi(w1,"start_zeny")==0){ 
			start_zeny=atoi(w2); 
			if(start_zeny < 0) start_zeny = 0; 
		} 
		else if(strcmpi(w1,"unknown_char_name")==0){ 
			strcpy(unknown_char_name,w2); 
			unknown_char_name[24] = 0; 
		} 
		else if(strcmpi(w1,"char_log_filename")==0){ 
			strcpy(char_log_filename,w2); 
		} 
		else if(strcmpi(w1,"import")==0){ 
			char_config_read(w2); 
		} 
	} 
	fclose(fp); 
 
	return 0; 
} 
 
void do_final(void) 
{ 
	mmo_char_sync(); 
	inter_save(); 
} 
 
int do_init(int argc,char **argv) 
{ 
	int i; 
 
	char_config_read((argc<2)? CHAR_CONF_NAME:argv[1]); 
 
	login_ip=inet_addr(login_ip_str); 
	char_ip=inet_addr(char_ip_str); 
 
	for(i=0;i2)?argv[2]:inter_cfgName);	// inter server 弶婜壔 
 
//	set_termfunc(mmo_char_sync); 
	set_termfunc(do_final); 
	set_defaultparse(parse_char); 
 
	make_listen_port(char_port); 
 
	add_timer_func_list(check_connect_login_server,"check_connect_login_server"); 
	add_timer_func_list(send_users_tologin,"send_users_tologin"); 
	add_timer_func_list(mmo_char_sync_timer,"mmo_char_sync_timer"); 
 
	i=add_timer_interval(gettick()+1000,check_connect_login_server,0,0,10*1000); 
	i=add_timer_interval(gettick()+1000,send_users_tologin,0,0,5*1000); 
	i=add_timer_interval(gettick()+autosave_interval,mmo_char_sync_timer,0,0,autosave_interval); 
 
	return 0; 
}