/** * Player requesting to change map-serv * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ int chmapif_parse_reqchangemapserv(int fd){ if (RFIFOREST(fd) < 39) return 0; { int map_id, map_fd = -1; struct mmo_charstatus* char_data; struct mmo_charstatus char_dat; DBMap* char_db_ = char_get_chardb(); map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) map_fd = map_server[map_id].fd; //Char should just had been saved before this packet, so this should be safe. [Skotlex] char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); if (char_data == NULL) { //Really shouldn't happen. char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } if( runflag == CHARSERVER_ST_RUNNING && session_isActive(map_fd) && char_data ) { //Send the map server the auth of this player. struct online_char_data* data; struct auth_node* node; DBMap* auth_db = char_get_authdb(); DBMap* online_char_db = char_get_onlinedb(); int aid = RFIFOL(fd,2); //Update the "last map" as this is where the player must be spawned on the new map server. char_data->last_point.map = RFIFOW(fd,18); char_data->last_point.x = RFIFOW(fd,20); char_data->last_point.y = RFIFOW(fd,22); char_data->sex = RFIFOB(fd,30); // create temporary auth entry CREATE(node, struct auth_node, 1); node->account_id = aid; node->char_id = RFIFOL(fd,14); node->login_id1 = RFIFOL(fd,6); node->login_id2 = RFIFOL(fd,10); node->sex = RFIFOB(fd,30); node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) node->ip = ntohl(RFIFOL(fd,31)); node->group_id = RFIFOL(fd,35); node->changing_mapservers = 1; idb_put(auth_db, aid, node); data = idb_ensure(online_char_db, aid, char_create_online_data); data->char_id = char_data->char_id; data->server = map_id; //Update server where char is. //Reply with an ack. chmapif_changemapserv_ack(fd,0); } else { //Reply with nak chmapif_changemapserv_ack(fd,1); } RFIFOSKIP(fd,39); }
struct guild_storage *guild2storage(int guild_id) { struct guild_storage *gs = NULL; if(guild_search(guild_id) != NULL) gs = idb_ensure(guild_storage_db,guild_id,create_guildstorage); return gs; }
/** * Map-serv sent us all his users info, (aid and cid) so we can update online_char_db * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_regmapuser(int fd, int id){ if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; { //TODO: When data mismatches memory, update guild/party online/offline states. DBMap* online_char_db = char_get_onlinedb(); int i; map_server[id].users = RFIFOW(fd,4); online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' for(i = 0; i < map_server[id].users; i++) { int aid = RFIFOL(fd,6+i*8); int cid = RFIFOL(fd,6+i*8+4); struct online_char_data* character = idb_ensure(online_char_db, aid, char_create_online_data); if( character->server > -1 && character->server != id ) { ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, id, aid, cid); mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); } character->server = id; character->char_id = cid; } //If any chars remain in -2, they will be cleaned in the cleanup timer. RFIFOSKIP(fd,RFIFOW(fd,2)); } return 1; }
int mapif_save_pet(int fd,int account_id,struct s_pet *data) { struct s_pet *p; int pet_id, len; RFIFOHEAD(fd); len=RFIFOW(fd,2); if(sizeof(struct s_pet)!=len-8) { ShowError("inter pet: data size error %d %d\n",sizeof(struct s_pet),len-8); } else{ pet_id = data->pet_id; if (pet_id == 0) pet_id = data->pet_id = pet_newid++; p = (struct s_pet*)idb_ensure(pet_db,pet_id,create_pet); if(data->hungry < 0) data->hungry = 0; else if(data->hungry > 100) data->hungry = 100; if(data->intimate < 0) data->intimate = 0; else if(data->intimate > 1000) data->intimate = 1000; memcpy(p,data,sizeof(struct s_pet)); if(p->incuvate == 1) p->account_id = p->char_id = 0; mapif_save_pet_ack(fd,account_id,0); } return 0; }
/** * Receive info from char-serv that this user is online * This function will start a timer to recheck if that user still online * @param char_server : Serv id where account_id is connected * @param account_id : aid connected * @return the new online_login_data for that user */ struct online_login_data* login_add_online_user(int char_server, uint32 account_id){ struct online_login_data* p; p = (struct online_login_data*)idb_ensure(online_db, account_id, login_create_online_user); p->char_server = char_server; if( p->waiting_disconnect != INVALID_TIMER ) { delete_timer(p->waiting_disconnect, login_waiting_disconnect_timer); p->waiting_disconnect = INVALID_TIMER; } return p; }
/*========================================== * Loads (and creates if not found) an item from the db. *------------------------------------------ */ struct item_data* itemdb_load(int nameid) { struct item_data *id = idb_ensure(item_db,nameid,create_item_data); if (id == &dummy_item) { //Remove dummy_item, replace by real data. DBKey key; key.i = nameid; idb_remove(item_db,nameid); id = create_item_data(key, NULL); idb_put(item_db,nameid,id); } return id; }
int mapif_save_homun(int fd,int account_id,struct s_homunculus *data) { struct s_homunculus *p; int hom_id; if (data->hom_id == 0) data->hom_id = homun_newid++; hom_id = data->hom_id; p = (struct s_homunculus*)idb_ensure(homun_db,hom_id,create_homun); memcpy(p,data,sizeof(struct s_homunculus)); mapif_save_homun_ack(fd,account_id,1); return 0; }
/// Writes provided data into storage cache. /// If data contains 0 items, any existing entry in cache is destroyed. /// If data contains 1+ items and no cache entry exists, a new one is created. bool storage_save(int account_id, struct storage_data* storage) { if( storage->storage_amount > 0 ) { struct storage_data* s = (struct storage_data*)idb_ensure(storage_db, account_id, create_storage); memcpy(s, storage, sizeof(*storage)); } else { idb_remove(storage_db, account_id); } return true; }
/** * Receive list of all online accounts. * @author [Skotlex] * @param fd: fd to parse from (char-serv) * @param id: id of char-serv * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_updonlinedb(int fd, int id){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; else{ uint32 i, users; online_db->foreach(online_db, login_online_db_setoffline, id); //Set all chars from this char-server offline first users = RFIFOW(fd,4); for (i = 0; i < users; i++) { int aid = RFIFOL(fd,6+i*4); struct online_login_data *p = (struct online_login_data*)idb_ensure(online_db, aid, login_create_online_user); p->char_server = id; if (p->waiting_disconnect != INVALID_TIMER){ delete_timer(p->waiting_disconnect, login_waiting_disconnect_timer); p->waiting_disconnect = INVALID_TIMER; } } RFIFOSKIP(fd,RFIFOW(fd,2)); } return 1; }
// 情報所得 int party_recv_info(struct party *sp) { struct map_session_data *sd; struct party *p; int i; nullpo_retr(0, sp); p= idb_ensure(party_db, sp->party_id, create_party); if (!p->party_id) //party just received. party_check_member(sp); memcpy(p,sp,sizeof(struct party)); for(i=0;i<MAX_PARTY;i++){ // sdの設定 if (!p->member[i].account_id) { p->member[i].sd=NULL; continue; } sd = map_id2sd(p->member[i].account_id); p->member[i].sd = (sd!=NULL && sd->status.party_id==p->party_id && sd->status.char_id == p->member[i].char_id && !sd->state.waitingdisconnect)?sd:NULL; } for(i=0;i<MAX_PARTY;i++){ // 設定情報の送信 sd = p->member[i].sd; if(!sd) continue; // Refresh hp/xy state [LuzZza] clif_party_hp(sd); clif_party_xy(sd); if(sd->state.party_sent==0){ clif_party_main_info(p,-1); clif_party_option(p,sd,0x100); clif_party_info(p,-1); sd->state.party_sent=1; } } return 0; }
int party_recv_info(struct party *sp) { struct party_data *p; int i; bool party_new = false; nullpo_retr(0, sp); p = (struct party_data*)idb_ensure(party_db, sp->party_id, create_party); if (!p->party.party_id) //party just received. { party_new = true; party_check_member(sp); } memcpy(&p->party,sp,sizeof(struct party)); memset(&p->state, 0, sizeof(p->state)); memset(&p->data, 0, sizeof(p->data)); for(i=0;i<MAX_PARTY;i++){ if (!p->party.member[i].account_id) continue; p->data[i].sd = party_sd_check(p->party.party_id, p->party.member[i].account_id, p->party.member[i].char_id); } party_check_state(p); if (party_new) { //Send party data to all players. struct map_session_data *sd; for(i=0;i<MAX_PARTY;i++){ sd = p->data[i].sd; if(!sd) continue; clif_charnameupdate(sd); //Update other people's display. [Skotlex] clif_party_member_info(p,sd); clif_party_option(p,sd,0x100); clif_party_info(p,NULL); } } return 0; }
int party_recv_info(struct party *sp) { struct map_session_data *sd; struct party_data *p; int i; nullpo_retr(0, sp); p= idb_ensure(party_db, sp->party_id, create_party); if (!p->party.party_id) //party just received. party_check_member(sp); memcpy(&p->party,sp,sizeof(struct party)); memset(&p->state, 0, sizeof(p->state)); memset(&p->data, 0, sizeof(p->data)); for(i=0;i<MAX_PARTY;i++){ if (!p->party.member[i].account_id) continue; sd = map_id2sd(p->party.member[i].account_id); if (sd && sd->status.party_id==p->party.party_id && sd->status.char_id == p->party.member[i].char_id && !sd->state.waitingdisconnect) p->data[i].sd = sd; } party_check_state(p); for(i=0;i<MAX_PARTY;i++){ sd = p->data[i].sd; if(!sd || sd->state.party_sent) continue; clif_party_member_info(p,sd); clif_party_option(p,sd,0x100); clif_party_info(p,NULL); sd->state.party_sent=1; } return 0; }
/*========================================== * Loads an item from the db. If not found, it will return the dummy item. *------------------------------------------ */ struct item_data* itemdb_search(int nameid) { return idb_ensure(item_db,nameid,return_dummy_data); }
struct storage *account2storage(int account_id) { return idb_ensure(storage_db,account_id,create_storage); }
/*========================================== * Loads (and creates if not found) an item from the db. *------------------------------------------ */ struct item_data* itemdb_load(int nameid) { return idb_ensure(item_db,nameid,create_item_data); }
// アカウントから倉庫データインデックスを得る(新規倉庫追加可能) struct storage *account2storage(int account_id) { struct storage *s; s= idb_ensure(storage_db, account_id, create_storage); return s; }