Ejemplo n.º 1
0
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
/// Returns a chatroom object on success, or NULL on failure.
static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev)
{
	struct chat_data* cd;
	nullpo_retr(NULL, bl);

	cd = (struct chat_data *) aMalloc(sizeof(struct chat_data));

	safestrncpy(cd->title, title, sizeof(cd->title));
	safestrncpy(cd->pass, pass, sizeof(cd->pass));
	cd->pub = pub;
	cd->users = 0;
	cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
	cd->trigger = trigger;
	memset(cd->usersd, 0, sizeof(cd->usersd));
	cd->owner = bl;
	safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));

	cd->bl.m    = bl->m;
	cd->bl.x    = bl->x;
	cd->bl.y    = bl->y;
	cd->bl.type = BL_CHAT;
	cd->bl.next = cd->bl.prev = NULL;
	cd->bl.id   = map_addobject(&cd->bl);

	if( cd->bl.id == 0 )
	{
		aFree(cd);
		cd = NULL;
	}

	return cd;
}
Ejemplo n.º 2
0
// Adds a map to the cache
void cache_map(char *name, struct map_data *m)
{
	struct map_info info;
	unsigned long len;
	unsigned char *write_buf;

	// Create an output buffer twice as big as the uncompressed map... this way we're sure it fits
	len = (unsigned long)m->xs*(unsigned long)m->ys*2;
	write_buf = (unsigned char *)aMalloc(len);
	// Compress the cells and get the compressed length
	encode_zip(write_buf, &len, m->cells, m->xs*m->ys);

	// Fill the map header
	if (strlen(name) > MAP_NAME_LENGTH) // It does not hurt to warn that there are maps with name longer than allowed.
		ShowWarning ("Map name '%s' size '%d' is too long. Truncating to '%d'.\n", name, strlen(name), MAP_NAME_LENGTH);
	strncpy(info.name, name, MAP_NAME_LENGTH);
	info.xs = MakeShortLE(m->xs);
	info.ys = MakeShortLE(m->ys);
	info.len = MakeLongLE(len);

	// Append map header then compressed cells at the end of the file
	fseek(map_cache_fp, header.file_size, SEEK_SET);
	fwrite(&info, sizeof(struct map_info), 1, map_cache_fp);
	fwrite(write_buf, 1, len, map_cache_fp);
	header.file_size += sizeof(struct map_info) + len;
	header.map_count++;

	aFree(write_buf);
	aFree(m->cells);

	return;
}
Ejemplo n.º 3
0
void clan_load_clandata( int count, struct clan* clans ){
	int i,j;

	nullpo_retv( clans );

	for( i = 0, j = 0; i < count; i++, clans++ ){
		struct clan* clan = clans;
		struct clan* clanCopy;

		clanCopy = (struct clan*)aMalloc( sizeof( struct clan ) );

		if( clanCopy == NULL ){
			ShowError("Memory could not be allocated for a clan.\n");
			break;
		}

		memcpy( clanCopy, clan, sizeof( struct clan ) );
		memset( clanCopy->members, 0, sizeof( clanCopy->members ) );

		idb_put( clan_db, clanCopy->id, clanCopy );
		j++;
	}

	ShowStatus( "Received '"CL_WHITE"%d"CL_RESET"' clans from char-server.\n", j );
}
Ejemplo n.º 4
0
/*==========================================
 * 傭兵作成
 *------------------------------------------
 */
bool mercdb_sql_new(struct mmo_mercstatus *p)
{
	bool result;
	struct mmo_mercstatus *p2;

	nullpo_retr(false, p);

	result = sqldbs_query(&mysql_handle,
		"INSERT INTO `" MERC_TABLE "` (`class`,`account_id`,`char_id`,`hp`,`sp`,`kill_count`,`limit`) "
		"VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%u')",
		p->class_, p->account_id, p->char_id, p->hp, p->sp, p->kill_count, p->limit
	);
	if(result == false) {
		p->merc_id = -1;
		return false;
	}

	p->merc_id = (int)sqldbs_insert_id(&mysql_handle);

	p2 = (struct mmo_mercstatus*)aMalloc(sizeof(struct mmo_mercstatus));
	memcpy(p2, p, sizeof(struct mmo_mercstatus));
	numdb_insert(merc_db, p->merc_id, p2);

	return true;
}
Ejemplo n.º 5
0
void geoip_readdb(void){
	struct stat bufa;
	FILE *db=fopen("./db/GeoIP.dat","rb");
	fstat(fileno(db), &bufa);
	geoip_cache = (unsigned char *) aMalloc(sizeof(unsigned char) * bufa.st_size);
	if(fread(geoip_cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size) { ShowError("geoip_cache reading didn't read all elements \n"); }
	fclose(db);
	ShowStatus("Finished Reading " CL_GREEN "GeoIP" CL_RESET " Database.\n");
}
Ejemplo n.º 6
0
/*==========================================
 * キャラIDからクエストデータを取得
 *------------------------------------------
 */
const struct quest *questdb_sql_load(int char_id)
{
	bool result = false;
	struct quest *q = (struct quest *)numdb_search(quest_db, char_id);

	if(q && q->char_id == char_id) {
		// 既にキャッシュが存在する
		return q;
	}
	if(q == NULL) {
		q = (struct quest *)aMalloc(sizeof(struct quest));
		numdb_insert(quest_db, char_id, q);
	}
	memset(q, 0, sizeof(struct quest));

	q->char_id = char_id;

	result = sqldbs_query(&mysql_handle,
		"SELECT `account_id`,`nameid`,`state`,`limit`,`mobid1`,`mobmax1`,`mobcnt1`,`mobid2`,`mobmax2`,`mobcnt2`,`mobid3`,`mobmax3`,`mobcnt3` "
		"FROM `" QUEST_TABLE "` WHERE `char_id`='%d'", char_id
	);
	if(result == false) {
		q->char_id = -1;
		return NULL;
	}

	if(sqldbs_num_rows(&mysql_handle) > 0) {
		int i;
		char **sql_row;

		for(i = 0; (sql_row = sqldbs_fetch(&mysql_handle)) && i < MAX_QUESTLIST; i++) {
			if(q->account_id == 0) {
				q->account_id = atoi(sql_row[0]);
			}
			q->data[i].nameid     = atoi(sql_row[1]);
			q->data[i].state      = (char)atoi(sql_row[2]);
			q->data[i].limit      = (unsigned int)atoi(sql_row[3]);
			q->data[i].mob[0].id  = (short)atoi(sql_row[4]);
			q->data[i].mob[0].max = (short)atoi(sql_row[5]);
			q->data[i].mob[0].cnt = (short)atoi(sql_row[6]);
			q->data[i].mob[1].id  = (short)atoi(sql_row[7]);
			q->data[i].mob[1].max = (short)atoi(sql_row[8]);
			q->data[i].mob[1].cnt = (short)atoi(sql_row[9]);
			q->data[i].mob[2].id  = (short)atoi(sql_row[10]);
			q->data[i].mob[2].max = (short)atoi(sql_row[11]);
			q->data[i].mob[2].cnt = (short)atoi(sql_row[12]);
		}
		q->count = (i < MAX_QUESTLIST)? i: MAX_QUESTLIST;
	} else {
		// 見つからなくても正常
		q = NULL;
	}
	sqldbs_free_result(&mysql_handle);

	return q;
}
Ejemplo n.º 7
0
// Reads a map from GRF's GAT and RSW files
int read_map(char *name, struct map_data *m)
{
	char filename[256];
	unsigned char *gat, *rsw;
	int water_height;
	size_t xy, off, num_cells;
	float height;
	uint32 type;

	// Open map GAT
	sprintf(filename,"data\\%s.gat", name);
	gat = (unsigned char *)grfio_read(filename);
	if (gat == NULL)
		return 0;

	// Open map RSW
	sprintf(filename,"data\\%s.rsw", name);
	rsw = (unsigned char *)grfio_read(filename);

	// Read water height
	if (rsw) {
		water_height = (int)GetFloat(rsw+166);
		aFree(rsw);
	} else
		water_height = NO_WATER;

	// Read map size and allocate needed memory
	m->xs = (int16)GetULong(gat+6);
	m->ys = (int16)GetULong(gat+10);
	if (m->xs <= 0 || m->ys <= 0) {
		aFree(gat);
		return 0;
	}
	num_cells = (size_t)m->xs*(size_t)m->ys;
	m->cells = (unsigned char *)aMalloc(num_cells);

	// Set cell properties
	off = 14;
	for (xy = 0; xy < num_cells; xy++)
	{
		// Height of the bottom-left corner
		height = GetFloat( gat + off      );
		// Type of cell
		type   = GetULong( gat + off + 16 );
		off += 20;

		if (type == 0 && water_height != NO_WATER && height > water_height)
			type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water)

		m->cells[xy] = (unsigned char)type;
	}

	aFree(gat);

	return 1;
}
Ejemplo n.º 8
0
/**
 * Reads GeoIP database and stores it into memory
 * geoip.cache should be freed after use!
 * http://dev.maxmind.com/geoip/legacy/geolite/
 **/
void geoip_init(void) {
	int i, fno;
	char db_type = 1;
	unsigned char delim[3];
	struct stat bufa;
	FILE *db;

	geoip.active = true;

	db = fopen("./db/GeoIP.dat","rb");
	if( db == NULL ) {
		ShowError("geoip_readdb: Error reading GeoIP.dat!\n");
		geoip_final(false);
		return;
	}
	fno = fileno(db);
	if( fstat(fno, &bufa) < 0 ) {
		ShowError("geoip_readdb: Error stating GeoIP.dat! Error %d\n", errno);
		geoip_final(false);
		return;
	}
	geoip.cache = aMalloc( (sizeof(geoip.cache) * bufa.st_size) );
	if( fread(geoip.cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size ) {
		ShowError("geoip_cache: Couldn't read all elements!\n");
		fclose(db);
		geoip_final(false);
		return;
	}

	// Search database type
	fseek(db, -3l, SEEK_END);
	for( i = 0; i < GEOIP_STRUCTURE_INFO_MAX_SIZE; i++ ) {
		fread(delim, sizeof(delim[0]), 3, db);
		if( delim[0] == 255 && delim[1] == 255 && delim[2] == 255 ) {
			fread(&db_type, sizeof(db_type), 1, db);
			break;
		} else {
			fseek(db, -4l, SEEK_CUR);
		}
	}
	
	fclose(db);

	if( db_type != 1 ) {
		if( db_type )
			ShowError("geoip_init(): Database type is not supported %d!\n", db_type);
		else
			ShowError("geoip_init(): GeoIP is corrupted!\n");

		geoip_final(false);
		return;
	}
	ShowStatus("Finished Reading "CL_GREEN"GeoIP"CL_RESET" Database.\n");
}
Ejemplo n.º 9
0
/**
 * Reads GeoIP database and stores it into memory
 * geoip.cache should be freed after use!
 * http://dev.maxmind.com/geoip/legacy/geolite/
 **/
void geoip_init(void) {
	int i, fno;
	char db_type = 1;
	unsigned char delim[3];
	struct stat bufa;
	FILE *db;

	geoip.active = true;

	db = fopen("./db/GeoIP.dat","rb");
	if(!db) {
		ShowError("[GeoDB] - Falha de leitura na base de dados GeoIP!\n");
		geoip_final(false);
		return;
	}
	fno = fileno(db);
	if( fstat(fno, &bufa) < 0 ) {
		ShowError("[GeoDB] - Falha em determinar tamanho do arquivo!\n");
		geoip_final(false);
		return;
	}
	geoip.cache = aMalloc( (sizeof(geoip.cache) * bufa.st_size) );
	if( fread(geoip.cache, 1, bufa.st_size, db) != bufa.st_size ) {
		ShowError("[GeoDB]: Leitura incompleta do arquivo GeoIP!\n");
		fclose(db);
		geoip_final(false);
		return;
	}

	// Search database type
	fseek(db, -3l, SEEK_END);
	for( i = 0; i < GEOIP_STRUCTURE_INFO_MAX_SIZE; i++ ) {
		(void)fread(delim, sizeof(delim[0]), 3, db); //(void) para remover aquele warning chato
		if( delim[0] == 255 && delim[1] == 255 && delim[2] == 255 ) {
			fread(&db_type, sizeof(db_type), 1, db);
			break;
		} else {
			fseek(db, -4l, SEEK_CUR);
		}
	}
	
	fclose(db);

	if( db_type != 1 ) {
		if( db_type )
			ShowError("[GeoDB] - Arquivo insuportado! (Tipo: %d)\n", db_type);
		else
			ShowError("[GeoDB] - Arquivo CORROMPIDO. \n");

		geoip_final(false);
		return;
	}
	ShowStatus("Finalizada leitura da base de dados "CL_GREEN"GeoIP"CL_RESET".\n");
}
Ejemplo n.º 10
0
// ギルド城情報所得時イベント追加
int guild_addcastleinfoevent(int castle_id,int index,const char *name)
{
	struct eventlist *ev;
	int code=castle_id|(index<<16);

	if( name==NULL || *name==0 )
		return 0;

	ev = (struct eventlist *)aMalloc(sizeof(struct eventlist));
	strncpy(ev->name,name,ARRAYLENGTH(ev->name));
	//The next event becomes whatever was currently stored.
	ev->next = (struct eventlist *)idb_put(guild_castleinfoevent_db,code,ev);
	return 0;
}
Ejemplo n.º 11
0
/*==========================================
 * 傭兵作成
 *------------------------------------------
 */
bool mercdb_txt_new(struct mmo_mercstatus *p2)
{
	struct mmo_mercstatus *p1;

	nullpo_retr(false, p2);

	p1 = (struct mmo_mercstatus *)aMalloc(sizeof(struct mmo_mercstatus));
	p2->merc_id = merc_newid++;

	memcpy(p1, p2, sizeof(struct mmo_mercstatus));
	numdb_insert(merc_db, p2->merc_id, p1);

	return true;
}
Ejemplo n.º 12
0
int add_timer_func_list(int (*func)(int,unsigned int,int,int), char* name)
{
	struct timer_func_list* tfl;

	if (name) {
		tfl = (struct timer_func_list*) aCalloc (sizeof(struct timer_func_list), 1);
		tfl->name = (char *) aMalloc (strlen(name) + 1);

		tfl->next = tfl_root;
		tfl->func = func;
		strcpy(tfl->name, name);
		tfl_root = tfl;
	}
	return 0;
}
Ejemplo n.º 13
0
// パーティ情報まとめ送り
int mapif_party_info(int fd,const struct party *p)
{
	size_t size = sizeof(struct party);
	unsigned char *buf = (unsigned char *)aMalloc(size+4);

	WBUFW(buf,0)=0x3821;
	WBUFW(buf,2)=(unsigned short)(size+4);
	memcpy(WBUFP(buf,4),p,size);
	if(fd<0)
		mapif_sendall(buf,WBUFW(buf,2));
	else
		mapif_send(fd,buf,WBUFW(buf,2));

	aFree(buf);
	return 0;
}
Ejemplo n.º 14
0
// broadcast sending
int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
{
	unsigned char *buf = (unsigned char*)aMalloc((len)*sizeof(unsigned char));

	WBUFW(buf,0) = 0x3800;
	WBUFW(buf,2) = len;
	WBUFL(buf,4) = fontColor;
	WBUFW(buf,8) = fontType;
	WBUFW(buf,10) = fontSize;
	WBUFW(buf,12) = fontAlign;
	WBUFW(buf,14) = fontY;
	memcpy(WBUFP(buf,16), mes, len - 16);
	chmapif_sendallwos(sfd, buf, len);

	aFree(buf);
	return 0;
}
Ejemplo n.º 15
0
netbuf netbuffer_get(sysint sz)
{
    sysint i;
    netbuf nb = NULL;

    // Search an appropriate pool
    for(i = 0; i < l_nPools; i++) {
        if(sz <= l_poolElemSize[i]) {
            // match

            nb = (netbuf)mempool_node_get(l_pool[i]);
            nb->pool = i;

            break;
        }
    }

    // No Bufferpool found that mets there quirements?.. (thats bad..)
    if(nb == NULL) {
        ShowWarning(read_message("Source.netbuffer_get"), sz);
        ShowWarning(read_message("Source.netbuffer_get2"));

        InterlockedIncrement(&l_nEmergencyAllocations);

        // .. better to check (netbuf struct provides 32 byte bufferspace itself.
        if(sz < 32) sz = 32;

        // allocate memory using malloc ..
        while(1) {
            nb = (netbuf) aMalloc((sizeof(struct netbuf) + sz - 32));
            if(nb != NULL) {
                memset(nb, 0x00, (sizeof(struct netbuf) + sz - 32));  // zero memory! (to enforce commit @ os.)
                nb->pool = -1; // emergency alloc.
                break;
            }

            rathread_yield();
        }// spin allocation.

    }


    nb->refcnt = 1;  // Initial refcount is 1

    return nb;
}//end: netbuffer_get()
Ejemplo n.º 16
0
/**
 * Reads Message Data.
 *
 * This is a modified version of the mapserver's msg_config_read to
 * only read messages with IDs between 550 and 550+MAX_JOB_NAMES.
 *
 * @param[in] cfg_name       configuration filename to read.
 * @param[in] allow_override whether to allow duplicate message IDs to override the original value.
 * @return success state.
 */
bool msg_config_read(const char *cfg_name, bool allow_override) {
	int msg_number;
	char line[1024], w1[1024], w2[1024];
	FILE *fp;
	static int called = 1;

	if((fp = fopen(cfg_name, "r")) == NULL) {
		ShowError(read_message("Source.reuse.reuse_file_not_found"), cfg_name);
		return 1;
	}

	if((--called) == 0)
		memset(msg_table, 0, sizeof(msg_table[0]) * MAX_JOB_NAMES);

	while(fgets(line, sizeof(line), fp)) {
		if(line[0] == '/' && line[1] == '/')
			continue;
		if(sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
			continue;

		if(strcmpi(w1, "import") == 0)
			msg_config_read(w2, true);
		else {
			msg_number = atoi(w1);
			if(msg_number < 550 || msg_number > (550+MAX_JOB_NAMES))
				continue;
			msg_number -= 550;
			if(msg_number >= 0 && msg_number < MAX_JOB_NAMES) {
				if (msg_table[msg_number] != NULL) {
					if (!allow_override) {
						ShowError("Duplicate message: ID '%d' was already used for '%s'. Message '%s' will be ignored.\n",
						          msg_number, w2, msg_table[msg_number]);
						continue;
					}
					aFree(msg_table[msg_number]);
				}
				msg_table[msg_number] = (char *)aMalloc((strlen(w2) + 1)*sizeof (char));
				strcpy(msg_table[msg_number],w2);
			}
		}
	}

	fclose(fp);

	return 0;
}
Ejemplo n.º 17
0
/**
 * Reads Message Data.
 *
 * This is a modified version of the mapserver's msg_config_read to
 * only read messages with IDs between 550 and 550+MAX_JOB_NAMES.
 *
 * @param[in] cfg_name       configuration filename to read.
 * @param[in] allow_override whether to allow duplicate message IDs to override the original value.
 * @return success state.
 */
bool msg_config_read(const char *cfg_name, bool allow_override) {
	int msg_number;
	char line[1024], w1[1024], w2[1024];
	FILE *fp;
	static int called = 1;

	if ((fp = fopen(cfg_name, "r")) == NULL) {
		ShowError("Arquivo inexistente: %s\n", cfg_name);
		return 1;
	}

	if ((--called) == 0)
		memset(msg_table, 0, sizeof(msg_table[0]) * MAX_JOB_NAMES);

	while(fgets(line, sizeof(line), fp) ) {
		if (line[0] == '/' && line[1] == '/')
			continue;
		if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
			continue;

		if (strcasecmp(w1, "import") == 0)
			msg_config_read(w2, true);
		else {
			msg_number = atoi(w1);
			if( msg_number < 550 || msg_number > (550+MAX_JOB_NAMES) )
				continue;
			msg_number -= 550;
			if (msg_number >= 0 && msg_number < MAX_JOB_NAMES) {
				if (msg_table[msg_number] != NULL) {
					if (!allow_override) {
						ShowError("Mensagem duplicada! (ID:'%d' | Uso:'%s'). Mensagem '%s' ignorada.\n",
						          msg_number, w2, msg_table[msg_number]);
						continue;
					}
					aFree(msg_table[msg_number]);
				}
				msg_table[msg_number] = aMalloc((strlen(w2) + 1)*sizeof (char));
				strcpy(msg_table[msg_number],w2);
			}
		}
	}

	fclose(fp);

	return 0;
}
Ejemplo n.º 18
0
int read_gm_account()
{
	char line[8192];
	struct gm_account *p;
	FILE *fp;
	int line_counter = 0, gm_counter = 0;
	
	ShowStatus("Starting reading gm_account\n");
	
	if( (fp = fopen(GM_ACCOUNT_NAME,"r")) == NULL )
		return 1;
	
	gm_account_db = idb_alloc(DB_OPT_RELEASE_DATA);
	
	while(fgets(line,sizeof(line),fp))
	{
		line_counter++;
		if ((line[0] == '/' && line[1] == '/') || line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
			continue;
		
		p = (struct gm_account*)aMalloc(sizeof(struct gm_account));
		if(p==NULL){
			ShowFatalError("gm_account: out of memory!\n");
			exit(EXIT_FAILURE);
		}
		
		if(sscanf(line,"%d %d",&p->account_id,&p->level) != 2 || p->level <= 0) {
			ShowWarning("gm_account: unsupported data format [conf/GM_account.txt] on line %d\n", line_counter);
			continue;
		}
		else {
			if(p->level > 99)
				p->level = 99;
			p = idb_put(gm_account_db,p->account_id,p);
			if( p )
				aFree(p);// old entry replaced
			gm_counter++;
			ShowInfo("GM ID: %d Level: %d\n",p->account_id,p->level);
		}
	}

	fclose(fp);
	ShowStatus("%d ID of gm_accounts read.\n", gm_counter);
	return 0;
}
Ejemplo n.º 19
0
/*==========================================
 * Read Message Data -- at char server we only keep job names.
 *------------------------------------------*/
int msg_config_read (const char *cfgName)
{
	int msg_number;
	char line[1024], w1[1024], w2[1024];
	FILE *fp;
	static int called = 1;

	if ( (fp = fopen (cfgName, "r")) == NULL) {
		ShowError ("Arquivos de mensagens não encontrado: %s\n", cfgName);
		return 1;
	}

	if ( (--called) == 0)
		memset (msg_table, 0, sizeof (msg_table[0]) * MAX_JOB_NAMES);

	while (fgets (line, sizeof (line), fp)) {
		if (line[0] == '/' && line[1] == '/')
			continue;

		if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
			continue;

		if (strcmpi (w1, "import") == 0)
			msg_config_read (w2);
		else {
			msg_number = atoi (w1);

			if (msg_number < 550 || msg_number > (550 + MAX_JOB_NAMES))
				continue;

			msg_number -= 550;

			if (msg_number >= 0 && msg_number < MAX_JOB_NAMES) {
				if (msg_table[msg_number] != NULL)
					aFree (msg_table[msg_number]);

				msg_table[msg_number] = (char *) aMalloc ( (strlen (w2) + 1) * sizeof (char));
				strcpy (msg_table[msg_number], w2);
			}
		}
	}

	fclose (fp);
	return 0;
}
Ejemplo n.º 20
0
/*
 * Read txt file and store them into msg_table
 */
int _msg_config_read(const char* cfgName,int size, char ** msg_table)
{
	uint16 msg_number, msg_count = 0, line_num = 0;
	char line[1024], w1[8], w2[512];
	FILE *fp;
	static int called = 1;

	if ((fp = fopen(cfgName, "r")) == NULL) {
		ShowError("Messages file not found: %s\n", cfgName);
		return -1;
	}

	if ((--called) == 0)
		memset(msg_table, 0, sizeof (msg_table[0]) * size);

	while (fgets(line, sizeof (line), fp)) {
		line_num++;
		if (line[0] == '/' && line[1] == '/')
			continue;
		if (sscanf(line, "%7[^:]: %511[^\r\n]", w1, w2) != 2)
			continue;

		if (strcmpi(w1, "import") == 0)
			_msg_config_read(w2,size,msg_table);
		else {
			msg_number = atoi(w1);
			if (msg_number >= 0 && msg_number < size) {
				if (msg_table[msg_number] != NULL)
					aFree(msg_table[msg_number]);
				size_t len = strnlen(w2,sizeof(w2)) + 1;
				msg_table[msg_number] = (char *) aMalloc(len * sizeof (char));
				safestrncpy(msg_table[msg_number], w2, len);
				msg_count++;
			}
			else
				ShowWarning("Invalid message ID '%s' at line %d from '%s' file.\n",w1,line_num,cfgName);
		}
	}

	fclose(fp);
	ShowInfo("Done reading " CL_WHITE "'%d'" CL_RESET " messages in " CL_WHITE "'%s'" CL_RESET ".\n",msg_count,cfgName);

	return 0;
}
Ejemplo n.º 21
0
/*==========================================
 * セーブ
 *------------------------------------------
 */
bool mercdb_txt_save(struct mmo_mercstatus *p2)
{
	struct mmo_mercstatus *p1;

	nullpo_retr(false, p2);

	p1 = (struct mmo_mercstatus *)numdb_search(merc_db, p2->merc_id);
	if(p1 == NULL) {
		p1 = (struct mmo_mercstatus *)aMalloc(sizeof(struct mmo_mercstatus));
		numdb_insert(merc_db, p2->merc_id, p1);
	}
	memcpy(p1, p2, sizeof(struct mmo_mercstatus));

#ifdef TXT_JOURNAL
	if( merc_journal_enable )
		journal_write( &merc_journal, p1->merc_id, p1 );
#endif
	return true;
}
Ejemplo n.º 22
0
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
/// Returns a chatroom object on success, or NULL on failure.
struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
{
	struct chat_data* cd;
	nullpo_retr(NULL, bl);
	nullpo_retr(NULL, title);
	nullpo_retr(NULL, pass);
	nullpo_retr(NULL, ev);

	/* Given the overhead and the numerous instances (npc allocated or otherwise) wouldn't it be beneficial to have it use ERS? [Ind] */
	cd = (struct chat_data *) aMalloc(sizeof(struct chat_data));

	safestrncpy(cd->title, title, sizeof(cd->title));
	safestrncpy(cd->pass, pass, sizeof(cd->pass));
	cd->pub = pub;
	cd->users = 0;
	cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
	cd->trigger = trigger;
	cd->zeny = zeny;
	cd->minLvl = minLvl;
	cd->maxLvl = maxLvl;
	memset(cd->usersd, 0, sizeof(cd->usersd));
	cd->owner = bl;
	safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));

	cd->bl.id   = map->get_new_object_id();
	cd->bl.m    = bl->m;
	cd->bl.x    = bl->x;
	cd->bl.y    = bl->y;
	cd->bl.type = BL_CHAT;
	cd->bl.next = cd->bl.prev = NULL;

	if( cd->bl.id == 0 ) {
		aFree(cd);
		return NULL;
	}

	map->addiddb(&cd->bl);

	if( bl->type != BL_NPC )
		cd->kick_list = idb_alloc(DB_OPT_BASE);

	return cd;
}
Ejemplo n.º 23
0
int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data)
{	// Run One NPC_Event[OnAgitEliminate]
	char *name = (char*)data;
	size_t len = (name) ? strlen(name) : 0; 
	// the rest is dangerous, but let it crash,
	// if this happens, it's ruined anyway
	int c=0;

	if(agit_flag)	// Agit not already End
	{
		char *evname=(char*)aMalloc( (len + 10) * sizeof(char));
		memcpy(evname,name,len - 5);
		strcpy(evname + len - 5,"Eliminate");
		c = npc_event_do(evname);
		ShowStatus("NPC_Event:[%s] Run (%d) Events.\n",evname,c);
		aFree(evname); // [Lance] Should fix this
	}
	if(name) aFree(name);
	return 0;
}
Ejemplo n.º 24
0
// Link DB System - jAthena
void linkdb_insert( struct linkdb_node** head, void *key, void* data)
{
	struct linkdb_node *node;
	if( head == NULL ) return ;
	node = (struct linkdb_node*)aMalloc( sizeof(struct linkdb_node) );
	if( *head == NULL ) {
		// first node
		*head      = node;
		node->prev = NULL;
		node->next = NULL;
	} else {
		// link nodes
		node->next    = *head;
		node->prev    = (*head)->prev;
		(*head)->prev = node;
		(*head)       = node;
	}
	node->key  = key;
	node->data = data;
}
Ejemplo n.º 25
0
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
/// Returns a chatroom object on success, or NULL on failure.
static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
{
	struct chat_data* cd;
	nullpo_retr(NULL, bl);

	cd = (struct chat_data *) aMalloc(sizeof(struct chat_data));

	safestrncpy(cd->title, title, sizeof(cd->title));
	safestrncpy(cd->pass, pass, sizeof(cd->pass));
	cd->pub = pub;
	cd->users = 0;
	cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
	cd->trigger = trigger;
	cd->zeny = zeny;
	cd->minLvl = minLvl;
	cd->maxLvl = maxLvl;
	memset(cd->usersd, 0, sizeof(cd->usersd));
	cd->owner = bl;
	safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));

	cd->bl.id   = iMap->get_new_object_id();
	cd->bl.m    = bl->m;
	cd->bl.x    = bl->x;
	cd->bl.y    = bl->y;
	cd->bl.type = BL_CHAT;
	cd->bl.next = cd->bl.prev = NULL;

	if( cd->bl.id == 0 )
	{
		aFree(cd);
		cd = NULL;
	}

	iMap->addiddb(&cd->bl);

	if( bl->type != BL_NPC )
		cd->kick_list = idb_alloc(DB_OPT_BASE);
	
	return cd;
}
Ejemplo n.º 26
0
/*==========================================
 * Read Message Data
 *------------------------------------------*/
int _msg_config_read(const char* cfgName,int size, char ** msg_table)
{
    int msg_number;
    char line[1024], w1[1024], w2[1024];
    FILE *fp;
    static int called = 1;

    if ((fp = fopen(cfgName, "r")) == NULL) {
	ShowError("Messages file not found: %s\n", cfgName);
	return 1;
    }

    if ((--called) == 0)
	memset(msg_table, 0, sizeof (msg_table[0]) * size);

    while (fgets(line, sizeof (line), fp)) {
	if (line[0] == '/' && line[1] == '/')
	    continue;
	if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
	    continue;

	if (strcmpi(w1, "import") == 0)
	    _msg_config_read(w2,size,msg_table);
	else {
	    msg_number = atoi(w1);
	    if (msg_number >= 0 && msg_number < size) {
		if (msg_table[msg_number] != NULL)
		    aFree(msg_table[msg_number]);
		msg_table[msg_number] = (char *) aMalloc((strlen(w2) + 1) * sizeof (char));
		strcpy(msg_table[msg_number], w2);
	    }
	}
    }

    fclose(fp);
    ShowInfo("Finished reading %s.\n",cfgName);

    return 0;
}
Ejemplo n.º 27
0
/*==========================================
 * 傭兵IDから傭兵データをロード
 *------------------------------------------
 */
const struct mmo_mercstatus* mercdb_sql_load(int merc_id)
{
	char **sql_row;
	struct mmo_mercstatus *p = (struct mmo_mercstatus *)numdb_search(merc_db, merc_id);

	if(p && p->merc_id == merc_id) {
		return p;
	}
	if(p == NULL) {
		p = (struct mmo_mercstatus *)aMalloc(sizeof(struct mmo_mercstatus));
		numdb_insert(merc_db, merc_id, p);
	}
	memset(p, 0, sizeof(struct mmo_mercstatus));

	if( sqldbs_query(&mysql_handle, "SELECT `class`,`account_id`,`char_id`,`hp`,`sp`,`kill_count`,`limit` FROM `" MERC_TABLE "` WHERE `merc_id`='%d'", merc_id) == false )
	{
		p->merc_id = -1;
		return NULL;
	}

	if((sql_row = sqldbs_fetch(&mysql_handle)) != NULL) {
		p->merc_id    = merc_id;
		p->class_     = atoi(sql_row[0]);
		p->account_id = atoi(sql_row[1]);
		p->char_id    = atoi(sql_row[2]);
		p->hp         = atoi(sql_row[3]);
		p->sp         = atoi(sql_row[4]);
		p->kill_count = atoi(sql_row[5]);
		p->limit      = (unsigned int)atoi(sql_row[6]);
	} else {
		p->merc_id = -1;
		p = NULL;
	}
	sqldbs_free_result(&mysql_handle);

	return p;
}
Ejemplo n.º 28
0
void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count)
{
	unsigned int i;
	struct map_session_data* pl_sd;
	struct DBIterator *iter;
	struct s_search_store_search s;
	searchstore_searchall_t store_searchall;
	time_t querytime;
	DBMap *vending_db = vending_getdb();

	if( !battle_config.feature_search_stores ) {
		return;
	}

	if( !sd->searchstore.open ) {
		return;
	}

	if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) {
		ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id);
		return;
	}

	time(&querytime);

	if( sd->searchstore.nextquerytime > querytime ) {
		clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME);
		return;
	}

	if( !sd->searchstore.uses ) {
		clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT);
		return;
	}

	// validate lists
	for( i = 0; i < item_count; i++ ) {
		if( !itemdb_exists(itemlist[i]) ) {
			ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]);
			clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
			return;
		}
	}
	for( i = 0; i < card_count; i++ ) {
		if( !itemdb_exists(cardlist[i]) ) {
			ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]);
			clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
			return;
		}
	}

	if( max_price < min_price ) {
		swap(min_price, max_price);
	}

	sd->searchstore.uses--;
	sd->searchstore.type = type;
	sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay;

	// drop previous results
	searchstore_clear(sd);

	// allocate max. amount of results
	sd->searchstore.items = (struct s_search_store_info_item*)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults);

	// search
	s.search_sd  = sd;
	s.itemlist   = itemlist;
	s.cardlist   = cardlist;
	s.item_count = item_count;
	s.card_count = card_count;
	s.min_price  = min_price;
	s.max_price  = max_price;
	iter         = db_iterator(vending_db);

	for( pl_sd = dbi_first(iter); dbi_exists(iter);  pl_sd = dbi_next(iter) ) {
		if( sd == pl_sd ) {// skip own shop, if any
			continue;
		}

		if( !store_searchall(pl_sd, &s) ) {// exceeded result size
			clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT);
			break;
		}
	}

	dbi_destroy(iter);

	if( sd->searchstore.count ) {
		// reclaim unused memory
		sd->searchstore.items = (struct s_search_store_info_item*)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count);

		// present results
		clif_search_store_info_ack(sd);

		// one page displayed
		sd->searchstore.pages++;
	} else {
		// cleanup
		searchstore_clear(sd);

		// update uses
		clif_search_store_info_ack(sd);

		// notify of failure
		clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
	}
}
Ejemplo n.º 29
0
/**
 * Loads group configuration from config file into memory.
 * @private
 */
static void read_config(void)
{
	config_setting_t *groups = NULL;
	const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name
	int group_count = 0;
	
	if (conf_read_file(&pc_group_config, config_filename))
		return;

	groups = config_lookup(&pc_group_config, "groups");

	if (groups != NULL) {
		GroupSettings *group_settings = NULL;
		DBIterator *iter = NULL;
		int i, loop = 0;

		group_count = config_setting_length(groups);
		for (i = 0; i < group_count; ++i) {
			int id = 0, level = 0;
			const char *groupname = NULL;
			int log_commands = 0;
			config_setting_t *group = config_setting_get_elem(groups, i);

			if (!config_setting_lookup_int(group, "id", &id)) {
				ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i);
				config_setting_remove_elem(groups, i);
				--i;
				--group_count;
				continue;
			}

			if (id2group(id) != NULL) {
				ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i);
				config_setting_remove_elem(groups, i);
				--i;
				--group_count;
				continue;
			}

			config_setting_lookup_int(group, "level", &level);
			config_setting_lookup_bool(group, "log_commands", &log_commands);

			if (!config_setting_lookup_string(group, "name", &groupname)) {
				char temp[20];
				config_setting_t *name = NULL;
				snprintf(temp, sizeof(temp), "Group %d", id);
				if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL ||
				    !config_setting_set_string(name, temp)) {
					ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n",
					          id, config_setting_source_file(group), config_setting_source_line(group));
					continue;
				}
				config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer
			}

			if (name2group(groupname) != NULL) {
				ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname);
				config_setting_remove_elem(groups, i);
				--i;
				--group_count;
				continue;
			}

			CREATE(group_settings, GroupSettings, 1);
			group_settings->id = id;
			group_settings->level = level;
			group_settings->name = groupname;
			group_settings->log_commands = (bool)log_commands;
			group_settings->inherit = config_setting_get_member(group, "inherit");
			group_settings->commands = config_setting_get_member(group, "commands");
			group_settings->permissions = config_setting_get_member(group, "permissions");
			group_settings->inheritance_done = false;
			group_settings->root = group;
			group_settings->group_pos = i;

			strdb_put(pc_groupname_db, groupname, group_settings);
			idb_put(pc_group_db, id, group_settings);
			
		}
		group_count = config_setting_length(groups); // Save number of groups
		
		// Check if all commands and permissions exist
		iter = db_iterator(pc_group_db);
		for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
			config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions;
			int count = 0, j;

			// Make sure there is "commands" group
			if (commands == NULL)
				commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP);
			count = config_setting_length(commands);

			for (j = 0; j < count; ++j) {
				config_setting_t *command = config_setting_get_elem(commands, j);
				const char *name = config_setting_name(command);
				if (!atcommand_exists(name)) {
					ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name);
					config_setting_remove(commands, name);
					--j;
					--count;
				}
			}

			// Make sure there is "permissions" group
			if (permissions == NULL)
				permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP);
			count = config_setting_length(permissions);

			for(j = 0; j < count; ++j) {
				config_setting_t *permission = config_setting_get_elem(permissions, j);
				const char *name = config_setting_name(permission);
				int p;

				ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), p, strcmp(pc_g_permission_name[p].name, name) == 0);
				if (p == ARRAYLENGTH(pc_g_permission_name)) {
					ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name);
					config_setting_remove(permissions, name);
					--p;
					--count;
				}
			}
		}
		dbi_destroy(iter);

		// Apply inheritance
		i = 0; // counter for processed groups
		while (i < group_count) {
			iter = db_iterator(pc_group_db);
			for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
				config_setting_t *inherit = NULL,
				                 *commands = group_settings->commands,
					             *permissions = group_settings->permissions;
				int j, inherit_count = 0, done = 0;
				
				if (group_settings->inheritance_done) // group already processed
					continue; 

				if ((inherit = group_settings->inherit) == NULL ||
				    (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others
					++i;
					group_settings->inheritance_done = true;
					continue;
				}
				
				for (j = 0; j < inherit_count; ++j) {
					GroupSettings *inherited_group = NULL;
					const char *groupname = config_setting_get_string_elem(inherit, j);

					if (groupname == NULL) {
						ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j);
						config_setting_remove_elem(inherit,j);
						continue;
					}
					if ((inherited_group = name2group(groupname)) == NULL) {
						ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname);
						config_setting_remove_elem(inherit,j);
						continue;
					}
					if (!inherited_group->inheritance_done)
						continue; // we need to do that group first

					// Copy settings (commands/permissions) that are not defined yet
					if (inherited_group->commands != NULL) {
						int l = 0, commands_count = config_setting_length(inherited_group->commands);
						for (l = 0; l < commands_count; ++l)
							config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, l));
					}

					if (inherited_group->permissions != NULL) {
						int l = 0, permissions_count = config_setting_length(inherited_group->permissions);
						for (l = 0; l < permissions_count; ++l)
							config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, l));
					}

					++done; // copied commands and permissions from one of inherited groups
				}
				
				if (done == inherit_count) { // copied commands from all of inherited groups
					++i;
					group_settings->inheritance_done = true; // we're done with this group
				}
			}
			dbi_destroy(iter);

			if (++loop > group_count) {
				ShowWarning("pc_groups:read_config: Could not process inheritance rules, check your config '%s' for cycles...\n",
				            config_filename);
				break;
			}
		} // while(i < group_count)

		// Pack permissions into GroupSettings.e_permissions for faster checking
		iter = db_iterator(pc_group_db);
		for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
			config_setting_t *permissions = group_settings->permissions;
			int c, count = config_setting_length(permissions);

			for (c = 0; c < count; ++c) {
				config_setting_t *perm = config_setting_get_elem(permissions, c);
				const char *name = config_setting_name(perm);
				int val = config_setting_get_bool(perm);
				int j;

				if (val == 0) // does not have this permission
					continue;
				ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0);
				group_settings->e_permissions |= pc_g_permission_name[j].permission;
			}
		}
		dbi_destroy(iter);
	}

	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename);

	
	if( ( pc_group_max = group_count ) ) {
		DBIterator *iter = db_iterator(pc_group_db);
		GroupSettings *group_settings = NULL;
		int* group_ids = aMalloc( pc_group_max * sizeof(int) );
		int i = 0;
		for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
			group_ids[i++] = group_settings->id;
		}
		
		atcommand_db_load_groups(group_ids);
		
		aFree(group_ids);
		
		dbi_destroy(iter);
	}
}
Ejemplo n.º 30
0
/// opens accounts file, loads it, and starts a periodic saving timer
static bool account_db_txt_init(AccountDB* self)
{
	AccountDB_TXT* db = (AccountDB_TXT*)self;
	DBMap* accounts;
	FILE* fp;
	char line[2048];
	unsigned int version = 0;

	// create accounts database
	db->accounts = idb_alloc(DB_OPT_RELEASE_DATA);
	accounts = db->accounts;

	// open data file
	fp = fopen(db->account_db, "r");
	if( fp == NULL )
	{
		// no account file -> no account -> no login, including char-server (ERROR)
		ShowError(CL_RED"account_db_txt_init: Accounts file [%s] not found."CL_RESET"\n", db->account_db);
		return false;
	}

	// load data file
	while( fgets(line, sizeof(line), fp) != NULL )
	{
		int account_id, n;
		unsigned int v;
		struct mmo_account acc;
		struct mmo_account* tmp;
		struct DBIterator* iter;
		int (*compare)(const char* str1, const char* str2) = ( db->case_sensitive ) ? strcmp : stricmp;

		if( line[0] == '/' && line[1] == '/' )
			continue;

		n = 0;
		if( sscanf(line, "%d%n", &v, &n) == 1 && (line[n] == '\n' || line[n] == '\r') )
		{// format version definition
			version = v;
			continue;
		}

		n = 0;
		if( sscanf(line, "%d\t%%newid%%%n", &account_id, &n) == 1 && (line[n] == '\n' || line[n] == '\r') )
		{// auto-increment
			if( account_id > db->next_account_id )
				db->next_account_id = account_id;
			continue;
		}

		if( !mmo_auth_fromstr(&acc, line, version) )
		{
			ShowError("account_db_txt_init: skipping invalid data: %s", line);
			continue;
		}

		// apply constraints & checks here
		if( acc.sex != 'S' && (acc.account_id < START_ACCOUNT_NUM || acc.account_id > END_ACCOUNT_NUM) )
			ShowWarning("account_db_txt_init: account %d:'%s' has ID outside of the defined range for accounts (min:%d max:%d)!\n", acc.account_id, acc.userid, START_ACCOUNT_NUM, END_ACCOUNT_NUM);

		iter = accounts->iterator(accounts);
		for( tmp = (struct mmo_account*)iter->first(iter,NULL); iter->exists(iter); tmp = (struct mmo_account*)iter->next(iter,NULL) )
			if( compare(acc.userid, tmp->userid) == 0 )
					break;
		iter->destroy(iter);

		if( tmp != NULL )
		{// entry with identical username
			ShowWarning("account_db_txt_init: account %d:'%s' has same username as account %d. The account will be inaccessible!\n", acc.account_id, acc.userid, tmp->account_id);
		}

		if( idb_get(accounts, acc.account_id) != NULL )
		{// account id already occupied
			ShowError("account_db_txt_init: ID collision for account id %d! Discarding data for account '%s'...\n", acc.account_id, acc.userid);
			continue;
		}

		// record entry in db
		tmp = (struct mmo_account*)aMalloc(sizeof(struct mmo_account));
		memcpy(tmp, &acc, sizeof(struct mmo_account));
		idb_put(accounts, acc.account_id, tmp);

		if( acc.account_id >= db->next_account_id )
			db->next_account_id = acc.account_id + 1;
	}

	// close data file
	fclose(fp);

	// initialize data saving timer
	add_timer_func_list(mmo_auth_sync_timer, "mmo_auth_sync_timer");
	db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (intptr)db, AUTH_SAVING_INTERVAL);

	return true;
}