/*========================================== * ギルド倉庫のデッドロックチェック *------------------------------------------ */ int storage_guild_checklock(int guild_id) { int i; struct guild *g; struct guild_storage *stor; if((g = guild_search(guild_id)) == NULL) return 0; for(i = 0; i < g->max_member; i++) { struct map_session_data *sd = g->member[i].sd; if(sd && sd->state.storage_flag == 2) { // 倉庫を開いている人が居たのでOK return 0; } } // 誰も使用していないのでデッドロックを解除する stor = (struct guild_storage *)numdb_search(guild_storage_db, guild_id); if(stor) { stor->storage_status = 0; } intif_deadlock_guild_storage(guild_id); return 1; }
// ========================================== // アカウント変数のジャーナルのロールフォワード用コールバック関数 // ------------------------------------------ int accregdb_journal_rollforward( int key, void* buf, int flag ) { struct accreg* reg = (struct accreg *)numdb_search( accreg_db, key ); // 念のためチェック if( flag == JOURNAL_FLAG_WRITE && key != ((struct accreg*)buf)->account_id ) { printf("inter: accreg_journal: key != account_id !\n"); return 0; } // データの置き換え if( reg ) { if( flag == JOURNAL_FLAG_DELETE ) { numdb_erase( accreg_db, key ); aFree( reg ); } else { memcpy( reg, buf, sizeof(struct accreg) ); } return 1; } // 追加 if( flag != JOURNAL_FLAG_DELETE ) { reg = (struct accreg*) aCalloc( 1, sizeof( struct accreg ) ); memcpy( reg, buf, sizeof(struct accreg) ); numdb_insert( accreg_db, key, reg ); return 1; } return 0; }
/*========================================== * カプラ倉庫から出す *------------------------------------------ */ void storage_storageget(struct map_session_data *sd, int idx, int amount) { struct storage *stor; int flag; nullpo_retv(sd); nullpo_retv(stor = (struct storage *)numdb_search(storage_db,sd->status.account_id)); if(!stor->storage_status) return; if(idx < 0 || idx >= MAX_STORAGE) return; if(amount < 1 || amount > stor->store_item[idx].amount) return; if((flag = pc_additem(sd, &stor->store_item[idx], amount)) == 0) { storage_delitem(sd, stor, idx, amount); return; } clif_storageitemremoved(sd,idx,amount); clif_additem(sd,0,0,flag); clif_storageitemadded(sd,stor,idx,amount); return; }
/*========================================== * charid_dbへ追加(返信待ちがあれば返信) *------------------------------------------ */ void map_addchariddb(int charid,char *name) { struct charid2nick *p; int req=0; p=numdb_search(charid_db,charid); if(p==NULL){ // データベースにない p = malloc(sizeof(struct charid2nick)); if(p==NULL){ printf("out of memory : map_addchariddb\n"); exit(1); } p->req_id=0; }else numdb_erase(charid_db,charid); req=p->req_id; memcpy(p->nick,name,24); p->req_id=0; numdb_insert(charid_db,charid,p); if(req){ // 返信待ちがあれば返信 struct map_session_data *sd = map_id2sd(req); if(sd!=NULL) clif_solved_charname(sd,charid); } }
// 作成可否 int party_created(int account_id,int fail,int party_id,char *name) { struct map_session_data *sd; sd=map_id2sd(account_id); nullpo_retr(0, sd); if(fail==0){ struct party *p; sd->status.party_id=party_id; if((p=(struct party *) numdb_search(party_db,party_id))!=NULL){ ShowFatalError("party: id already exists!\n"); exit(1); } p=(struct party *)aCalloc(1,sizeof(struct party)); p->party_id=party_id; memcpy(p->name, name, NAME_LENGTH-1); numdb_insert(party_db,party_id,p); clif_party_created(sd,0); clif_charnameupdate(sd); //Update other people's display. [Skotlex] }else{ clif_party_created(sd,1); } return 0; }
// パーティマップ更新要求 int mapif_parse_PartyChangeMap(int fd,int party_id,int account_id,char *map,int online,int lv) { struct party *p; int i; p=numdb_search(party_db,party_id); if(p==NULL){ return 0; } for(i=0;i<MAX_PARTY;i++){ if(p->member[i].account_id==account_id){ int flag=0; memcpy(p->member[i].map,map,16); p->member[i].online=online; p->member[i].lv=lv; mapif_party_membermoved(p,i); if( p->exp>0 && !party_check_exp_share(p) ){ p->exp=0; flag=1; } if(flag) mapif_party_optionchanged(fd,p,0,0); break; } } if(online==0) // 誰かがログアウトするごとにセーブ inter_party_save(); return 0; }
// パーティ追加要求 int mapif_parse_PartyAddMember(int fd,int party_id,int account_id,char *nick,char *map,int lv) { struct party *p; int i; p=numdb_search(party_db,party_id); if(p==NULL){ mapif_party_memberadded(fd,party_id,account_id,1); return 0; } for(i=0;i<MAX_PARTY;i++){ if(p->member[i].account_id==0){ int flag=0; p->member[i].account_id=account_id; memcpy(p->member[i].name,nick,24); memcpy(p->member[i].map,map,16); p->member[i].leader=0; p->member[i].online=1; p->member[i].lv=lv; mapif_party_memberadded(fd,party_id,account_id,0); mapif_party_info(-1,p); if( p->exp>0 && !party_check_exp_share(p) ){ p->exp=0; flag=0x01; } if(flag) mapif_party_optionchanged(fd,p,0,0); return 0; } } mapif_party_memberadded(fd,party_id,account_id,1); return 0; }
/*========================================== * ギルド倉庫を開く *------------------------------------------ */ int storage_guild_storageopen(struct map_session_data *sd) { struct guild_storage *gstor; int gmlvl = 0; nullpo_retr(0, sd); if(sd->status.guild_id <= 0) return 2; if(sd->state.storage_flag == 2) return 3; // 既にギルド倉庫を開いている gmlvl = pc_isGM(sd); if(gmlvl > 0 && battle_config.gm_can_drop_lv > gmlvl) return 2; // 設定しているGMレベルより低い if(sd->state.storage_flag == 1) storage_storageclose(sd); // カプラ倉庫をすでに開いている場合閉じる if((gstor = (struct guild_storage *)numdb_search(guild_storage_db,sd->status.guild_id)) != NULL) { gstor->storage_status = 1; sd->state.storage_flag = 2; clif_guildstorageitemlist(sd,gstor); clif_guildstorageequiplist(sd,gstor); clif_updateguildstorageamount(sd,gstor); } else { intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); } return 0; }
//----------------------- // A member change of map //----------------------- void mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, char *map, unsigned char online, int lv) { // online: 0: offline, 1:online struct party *p; int i; p = numdb_search(party_db, (CPU_INT)party_id); if (p == NULL) return; for(i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id == account_id) { // same account can have more than character in same party. we must check name here too! memset(p->member[i].map, 0, sizeof(p->member[i].map)); strncpy(p->member[i].map, map, 16); // 17 - NULL p->member[i].online = online; // online: 0: offline, 1:online p->member[i].lv = lv; mapif_party_membermoved(p, i); if (p->exp > 0 && !party_check_exp_share(p)) { p->exp = 0; mapif_party_optionchanged(fd, p, 0, 0); } break; } } return; }
//--------------------------- // Adding a member in a party //--------------------------- void mapif_parse_PartyAddMember(int fd, int party_id, int account_id, char *nick, char *map, int lv) { struct party *p; int i; p = numdb_search(party_db, (CPU_INT)party_id); if (p == NULL) { mapif_party_memberadded(fd, party_id, account_id, 1); return; } for(i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id == 0) { // must we check if an other character of same account is in the party? p->member[i].account_id = account_id; memset(p->member[i].name, 0, sizeof(p->member[i].name)); strncpy(p->member[i].name, nick, 24); memset(p->member[i].map, 0, sizeof(p->member[i].map)); strncpy(p->member[i].map, map, 16); // 17 - NULL p->member[i].leader = 0; p->member[i].online = 1; p->member[i].lv = lv; mapif_party_memberadded(fd, party_id, account_id, 0); mapif_party_info(-1, p); if (p->exp > 0 && !party_check_exp_share(p)) { p->exp = 0; mapif_party_optionchanged(fd, p, 0, 0); } return; } } mapif_party_memberadded(fd, party_id, account_id, 1); return; }
// 検索 struct party *party_search(int party_id) { if (party_cache && party_cache->party_id == party_id) return party_cache; party_cache = (struct party *) numdb_search(party_db,party_id); return party_cache; }
int isGM(int account_id) { struct gm_account *p; p = (struct gm_account*)numdb_search(gm_account_db,account_id); if( p == NULL) return 0; return p->level; }
/*========================================== * char_id番号の名前を探す *------------------------------------------ */ char * map_charid2nick(int id) { struct charid2nick *p=numdb_search(charid_db,id); if(p==NULL) return NULL; if(p->req_id!=0) return NULL; return p->nick; }
/*========================================== * セーブ *------------------------------------------ */ bool questdb_sql_save(struct quest *q2) { const struct quest *q1; bool result = false; nullpo_retr(false, q2); q1 = questdb_sql_load(q2->char_id); if(q1 && q1->count <= 0 && q2->count <= 0) { // データが共に0個なので何もしない return true; } if( sqldbs_transaction_start(&mysql_handle) == false ) return false; // try do { int i; if(q1 == NULL || q1->count > 0) { // データサーバ側にデータがあるときだけ削除クエリを発行 if( sqldbs_query(&mysql_handle, "DELETE FROM `" QUEST_TABLE "` WHERE `char_id`='%d'", q2->char_id) == false ) break; } for(i = 0; i < q2->count; i++) { if( sqldbs_query(&mysql_handle, "INSERT INTO `" QUEST_TABLE "` (`char_id`, `account_id`, `nameid`, `state`, `limit`, `mobid1`, `mobmax1`, `mobcnt1`, " "`mobid2`, `mobmax2`, `mobcnt2`, `mobid3`, `mobmax3`, `mobcnt3`) " "VALUES ('%d','%d','%d','%d','%u','%d','%d','%d','%d','%d','%d','%d','%d','%d')", q2->char_id, q2->account_id, q2->data[i].nameid, q2->data[i].state, q2->data[i].limit, q2->data[i].mob[0].id, q2->data[i].mob[0].max, q2->data[i].mob[0].cnt, q2->data[i].mob[1].id, q2->data[i].mob[1].max, q2->data[i].mob[1].cnt, q2->data[i].mob[2].id, q2->data[i].mob[2].max, q2->data[i].mob[2].cnt ) == false ) break; } if(i != q2->count) break; // success result = true; { // cache copy struct quest *q3 = (struct quest *)numdb_search(quest_db, q2->char_id); if(q3) memcpy(q3, q2, sizeof(struct quest)); } } while(0); sqldbs_transaction_end(&mysql_handle, result); return result; }
/*========================================== * id番号のPCを探す。居なければNULL *------------------------------------------ */ struct map_session_data * map_id2sd(int id) { struct block_list *bl; bl=numdb_search(id_db,id); if(bl && bl->type==BL_PC) return (struct map_session_data*)bl; return NULL; }
struct storage *account2storage(intptr_t account_id) { struct storage *stor; stor=numdb_search(storage_db, account_id); if (stor == NULL) { CALLOC(stor, struct storage, 1); stor->account_id = account_id; numdb_insert(storage_db, (intptr_t)stor->account_id, stor); }
/*========================================== * キャラ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; }
// パーティ情報要求 int mapif_parse_PartyInfo(int fd,int party_id) { struct party *p; p=numdb_search(party_db,party_id); if(p!=NULL) mapif_party_info(fd,p); else mapif_party_noinfo(fd,party_id); return 0; }
//---------------------------------- // Request to have party information //---------------------------------- void mapif_parse_PartyInfo(int fd, int party_id) { // 0x3021 <party_id>.L - ask for party struct party *p; p = numdb_search(party_db, (CPU_INT)party_id); if (p != NULL) mapif_party_info(fd, p); else mapif_party_noinfo(fd, party_id); return; }
// アカウントから倉庫データインデックスを得る(新規倉庫追加可能) struct storage *account2storage (int account_id) { struct storage *s; s = (struct storage *) numdb_search (storage_db, account_id); if (s == NULL) { CREATE (s, struct storage, 1); memset (s, 0, sizeof (struct storage)); s->account_id = account_id; numdb_insert (storage_db, s->account_id, s); }
// パーティ解散要求 int mapif_parse_BreakParty(int fd,int party_id) { struct party *p; p=numdb_search(party_db,party_id); if(p==NULL){ return 0; } numdb_erase(party_db,party_id); mapif_party_broken(fd,party_id); return 0; }
/*========================================== * Deletes status change data of the player given. [Skotlex] * Should be invoked after the data of said player was successfully loaded. *------------------------------------------ */ void status_delete_scdata(int aid, int cid) { struct scdata *scdata = numdb_search(scdata_db, cid); if (scdata) { if (scdata->data) aFree(scdata->data); numdb_erase(scdata_db, cid); aFree(scdata); } }
/*========================================== * アカウントIDから倉庫データをロード * (新規倉庫追加可能) *------------------------------------------ */ const struct storage* storagedb_txt_load(int account_id) { struct storage *s = (struct storage *)numdb_search(storage_db, account_id); if(s == NULL) { s = (struct storage *)aCalloc(1, sizeof(struct storage)); s->account_id = account_id; numdb_insert(storage_db, s->account_id, s); } return s; }
/*========================================== * カプラ倉庫データベース *------------------------------------------ */ static struct storage *account2storage(int account_id) { struct storage *stor; stor = (struct storage *)numdb_search(storage_db,account_id); if(stor == NULL) { stor = (struct storage *)aCalloc(1,sizeof(struct storage)); stor->account_id = account_id; numdb_insert(storage_db,stor->account_id,stor); } return stor; }
//----------------- // Break of a party //----------------- void mapif_parse_BreakParty(int fd, int party_id) { struct party *p; p = numdb_search(party_db, (CPU_INT)party_id); if (p == NULL) return; numdb_erase(party_db, (CPU_INT)party_id); mapif_party_broken(party_id); return; }
/*========================================== * Loads status change data of the player given. [Skotlex] *------------------------------------------ */ struct scdata* status_search_scdata(int aid, int cid) { struct scdata *data; data = numdb_search(scdata_db, cid); if (data == NULL) { data = aCalloc(1, sizeof(struct scdata)); data->account_id = aid; data->char_id = cid; numdb_insert(scdata_db, cid, data); } return data; }
/*========================================== * セーブ *------------------------------------------ */ bool mercdb_sql_save(struct mmo_mercstatus *p2) { char sep = ' '; char tmp_sql[65536]; char *p = tmp_sql; const struct mmo_mercstatus *p1; bool result = false; nullpo_retr(false, p2); p1 = mercdb_sql_load(p2->merc_id); if(p1 == NULL) return false; strcpy(p, "UPDATE `" MERC_TABLE "` SET"); p += strlen(p); UPDATE_NUM(class_ ,"class"); UPDATE_NUM(account_id ,"account_id"); UPDATE_NUM(char_id ,"char_id"); UPDATE_NUM(hp ,"hp"); UPDATE_NUM(sp ,"sp"); UPDATE_NUM(kill_count ,"kill_count"); UPDATE_UNUM(limit ,"limit"); if( sqldbs_transaction_start(&mysql_handle) == false ) return false; // try do { if(sep == ',') { sprintf(p, " WHERE `merc_id` = '%d'",p2->merc_id); if( sqldbs_simplequery(&mysql_handle, tmp_sql) == false ) break; } // success result = true; { // cache copy struct mmo_mercstatus *p3 = (struct mmo_mercstatus *)numdb_search(merc_db, p2->merc_id); if(p3) memcpy(p3, p2, sizeof(struct mmo_mercstatus)); } } while(0); sqldbs_transaction_end(&mysql_handle, result); return result; }
/*========================================== * アカウントIDから倉庫データをロード *------------------------------------------ */ const struct storage* storagedb_sql_load(int account_id) { struct storage *s = (struct storage *)numdb_search(storage_db, account_id); if(s == NULL) { s = (struct storage *)aCalloc(1, sizeof(struct storage)); s->account_id = account_id; numdb_insert(storage_db, s->account_id, s); s->storage_amount = chardb_sql_loaditem(s->store_item, MAX_STORAGE, account_id, TABLE_NUM_STORAGE); } return s; }
/*========================================== * Search in item database *------------------------------------------ */ struct item_data* itemdb_search(intptr_t nameid) { struct item_data *id; id=numdb_search(item_db,nameid); if(id) return id; CALLOC(id, struct item_data, 1); numdb_insert(item_db,nameid,id); id->nameid=nameid; id->value_buy=10; id->value_sell=id->value_buy/2; id->weight=10; id->sex=2; id->elv=0; id->class_base[0]=0xff; id->class_base[1]=0xff; id->class_base[2]=0xff; id->class_upper=5; id->flag.available=0; id->flag.value_notdc=0; id->flag.value_notoc=0; id->flag.no_equip=0; id->view_id=0; if (nameid > 500 && nameid < 600) id->type = 0; //heal item else if (nameid > 600 && nameid < 700) id->type = 2; //use item else if ((nameid > 700 && nameid < 1100) || (nameid > 7000 && nameid < 8000)) id->type = 3; //correction else if (nameid >= 1750 && nameid < 1771) id->type = 10; //arrow else if (nameid > 1100 && nameid < 2000) id->type = 4; //weapon else if ((nameid > 2100 && nameid < 3000) || (nameid > 5000 && nameid < 6000)) id->type = 5; //armor else if (nameid > 4000 && nameid < 5000) id->type = 6; //card else if (nameid > 9000 && nameid < 10000) id->type = 7; //egg else if (nameid > 10000) id->type = 8; //petequip return id; }
/*========================================== * ギルド倉庫の保存 *------------------------------------------ */ void storage_guild_storagesave(struct map_session_data *sd) { struct guild_storage *stor; nullpo_retv(sd); stor = (struct guild_storage *)numdb_search(guild_storage_db,sd->status.guild_id); if(stor && stor->dirty) { intif_send_guild_storage(sd->status.account_id,stor); stor->dirty = 0; } return; }