/// 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; }
// 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; }
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 ); }
/*========================================== * 傭兵作成 *------------------------------------------ */ 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; }
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"); }
/*========================================== * キャラ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; }
// 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; }
/** * 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"); }
/** * 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"); }
// ギルド城情報所得時イベント追加 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; }
/*========================================== * 傭兵作成 *------------------------------------------ */ 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; }
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; }
// パーティ情報まとめ送り 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; }
// 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; }
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()
/** * 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; }
/** * 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; }
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; }
/*========================================== * 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; }
/* * 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; }
/*========================================== * セーブ *------------------------------------------ */ 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; }
/// 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; }
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; }
// 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; }
/// 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; }
/*========================================== * 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; }
/*========================================== * 傭兵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; }
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); } }
/** * 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); } }
/// 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; }