int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 21) return 0; { uint32 account_id = RFIFOL(fd,2); uint32 login_id1 = RFIFOL(fd,6); uint32 login_id2 = RFIFOL(fd,10); uint8 sex = RFIFOB(fd,14); uint8 result = RFIFOB(fd,15); int request_id = RFIFOL(fd,16); uint8 clienttype = RFIFOB(fd,20); RFIFOSKIP(fd,21); if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) && !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex ) { int client_fd = request_id; sd->clienttype = clienttype; switch( result ) { case 0:// ok char_auth_ok(client_fd, sd); break; case 1:// auth failed chclif_reject(client_fd,0); // rejected from server break; } } } return 1; }
/* * Client request to change pincode */ int chclif_parse_pincode_change( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 14 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; else { char oldpin[PINCODE_LENGTH+1]; char newpin[PINCODE_LENGTH+1]; memset(oldpin,0,PINCODE_LENGTH+1); memset(newpin,0,PINCODE_LENGTH+1); strncpy(oldpin, RFIFOCP(fd,6), PINCODE_LENGTH); strncpy(newpin, RFIFOCP(fd,10), PINCODE_LENGTH); RFIFOSKIP(fd,14); char_pincode_decrypt(sd->pincode_seed,oldpin); if( !char_pincode_compare( fd, sd, oldpin ) ) return 1; char_pincode_decrypt(sd->pincode_seed,newpin); if( pincode_allowed(newpin) ){ chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); strncpy(sd->pincode, newpin, sizeof(newpin)); ShowInfo("Pincode changed for AID: %d\n", sd->account_id); chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL ); } } return 1; }
/** * 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); }
/** * This function is called when the map-serv initialise is chrif interface. * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary * We reply by sending back the char_serv_wisp_name fame list and * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_getmapname(int fd, int id){ int j = 0, i = 0; if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; //Retain what map-index that map-serv contains memset(map_server[id].map, 0, sizeof(map_server[id].map)); for(i = 4; i < RFIFOW(fd,2); i += 4) { map_server[id].map[j] = RFIFOW(fd,i); j++; } ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", id, j, CONVIP(map_server[id].ip), map_server[id].port); ShowStatus("Map-server %d loading complete.\n", id); // send name for wisp to player WFIFOHEAD(fd, 3 + NAME_LENGTH); WFIFOW(fd,0) = 0x2afb; WFIFOB(fd,2) = 0; //0 succes, 1:failure memcpy(WFIFOP(fd,3), charserv_config.wisp_server_name, NAME_LENGTH); WFIFOSET(fd,3+NAME_LENGTH); chmapif_send_fame_list(fd); //Send fame list. { int x; if (j == 0) { ShowWarning("Map-server %d has NO maps.\n", id); } else { unsigned char buf[16384]; // Transmitting maps information to the other map-servers WBUFW(buf,0) = 0x2b04; WBUFW(buf,2) = j * 4 + 10; WBUFL(buf,4) = htonl(map_server[id].ip); WBUFW(buf,8) = htons(map_server[id].port); memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); chmapif_sendallwos(fd, buf, WBUFW(buf,2)); } // Transmitting the maps of the other map-servers to the new map-server for(x = 0; x < ARRAYLENGTH(map_server); x++) { if (map_server[x].fd > 0 && x != id) { WFIFOHEAD(fd,10 +4*ARRAYLENGTH(map_server[x].map)); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(map_server[x].ip); WFIFOW(fd,8) = htons(map_server[x].port); j = 0; for(i = 0; i < ARRAYLENGTH(map_server[x].map); i++) if (map_server[x].map[i]) WFIFOW(fd,10+(j++)*4) = map_server[x].map[i]; if (j > 0) { WFIFOW(fd,2) = j * 4 + 10; WFIFOSET(fd,WFIFOW(fd,2)); } } } } RFIFOSKIP(fd,RFIFOW(fd,2)); return 1; }
/** * This function is called when the map-serv initialise is chrif interface. * Map-serv sent us his map indexes so we can transfert a player from a map-serv to another when necessary * We reply by sending back the char_serv_wisp_name fame list and * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_getmapname(int fd, int id){ int i = 0, j = 0; unsigned char *mapbuf; if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; //Retain what map-index that map-serv contains memset(map_server[id].map, 0, sizeof(map_server[id].map)); for(i = 4; i < RFIFOW(fd,2); i += 4) { map_server[id].map[j] = RFIFOW(fd,i); j++; } mapbuf = RFIFOP(fd,4); RFIFOSKIP(fd,RFIFOW(fd,2)); ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", id, j, CONVIP(map_server[id].ip), map_server[id].port); ShowStatus("Map-server %d loading complete.\n", id); chmapif_send_misc(fd); chmapif_send_fame_list(fd); //Send fame list. chmapif_send_maps(fd, id, j, mapbuf); return 1; }
//Request to save skill cooldown data int chmapif_parse_req_saveskillcooldown(int fd){ if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; else { int count, aid, cid; aid = RFIFOL(fd,4); cid = RFIFOL(fd,8); count = RFIFOW(fd,12); if( count > 0 ) { struct skill_cooldown_data data; StringBuf buf; int i; StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", schema_config.skillcooldown_db); for( i = 0; i < count; ++i ) { memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data)); if( i > 0 ) StringBuf_AppendStr(&buf, ", "); StringBuf_Printf(&buf, "('%d','%d','%d','%d')", aid, cid, data.skill_id, data.tick); } if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); StringBuf_Destroy(&buf); } RFIFOSKIP(fd, RFIFOW(fd, 2)); } return 1; }
int chlogif_parse_updip(int fd, struct char_session_data* sd){ unsigned char buf[2]; uint32 new_ip = 0; /** * !CHECKME: This is intended? Just tell if there's IP sync request * without sending current char IP (if changed) to map-server? **/ WBUFW(buf,0) = 0x2b1e; chmapif_sendall(buf, 2); new_ip = host2ip(charserv_config.login_ip_str); if (new_ip && new_ip != charserv_config.login_ip) charserv_config.login_ip = new_ip; //Update login ip, too. new_ip = host2ip(charserv_config.char_ip_str); if (new_ip && new_ip != charserv_config.char_ip) { // Char-server IP is updated. charserv_config.char_ip = new_ip; ShowInfo("Updating IP for [%s].\n", charserv_config.char_ip_str); // notify login server about the change WFIFOHEAD(fd,6); WFIFOW(fd,0) = 0x2736; WFIFOL(fd,2) = htonl(charserv_config.char_ip); WFIFOSET(fd,6); } RFIFOSKIP(fd,2); return 1; }
int chlogif_parse_askkick(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 6) return 0; else { DBMap* online_char_db = char_get_onlinedb(); DBMap* auth_db = char_get_authdb(); int aid = RFIFOL(fd,2); struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); RFIFOSKIP(fd,6); if( character != NULL ) {// account is already marked as online! if( character->server > -1 ) { //Kick it from the map server it is on. mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == INVALID_TIMER) character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, char_chardb_waiting_disconnect, character->account_id, 0); } else {// Manual kick from char server. struct char_session_data *tsd; int i; ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid ); if( i < fd_max ) { chclif_send_auth_result(i,2); //Send "Someone has already logged in with this id" set_eof(i); } else // still moving to the map-server char_set_char_offline(-1, aid); } } idb_remove(auth_db, aid);// reject auth attempts from map-server } return 1; }
int chlogif_parse_keepalive(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 2) return 0; RFIFOSKIP(fd,2); session[fd]->flag.ping = 0; return 1; }
/** * Receiving a sex change request (sex is reversed). * @param fd: fd to parse from (char-serv) * @param id: id of char-serv * @param ip: char-serv ip (used for info) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_reqchgsex(int fd, int id, char* ip){ if( RFIFOREST(fd) < 6 ) return 0; else{ struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); uint32 account_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); if( !accounts->load_num(accounts, &acc, account_id) ) ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip); else if( acc.sex == 'S' ) ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip); else{ unsigned char buf[7]; char sex = ( acc.sex == 'M' ) ? 'F' : 'M'; //Change gender ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", ch_server[id].name, account_id, sex, ip); acc.sex = sex; // Save accounts->save(accounts, &acc); // announce to other servers WBUFW(buf,0) = 0x2723; WBUFL(buf,2) = account_id; WBUFB(buf,6) = sex_str2num(sex); logchrif_sendallwos(-1, buf, 7); } } return 1; }
/** * Map server send information to change an email of an account via char-server. * 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B * @param fd: fd to parse from (char-serv) * @param id: id of char-serv * @param ip: char-serv ip (used for info) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_reqchangemail(int fd, int id, char* ip){ if (RFIFOREST(fd) < 86) return 0; else{ struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); char actual_email[40]; char new_email[40]; uint32 account_id = RFIFOL(fd,2); safestrncpy(actual_email, RFIFOCP(fd,6), 40); safestrncpy(new_email, RFIFOCP(fd,46), 40); RFIFOSKIP(fd, 86); if( e_mail_check(actual_email) == 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip); else if( e_mail_check(new_email) == 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip); else if( strcmpi(new_email, "*****@*****.**") == 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip); else if( !accounts->load_num(accounts, &acc, account_id) ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip); else if( strcmpi(acc.email, actual_email) != 0 ) ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, acc.email, actual_email, ip); else{ safestrncpy(acc.email, new_email, 40); ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, new_email, ip); // Save accounts->save(accounts, &acc); } } return 1; }
// map server からの通信(1パケットのみ解析すること) // エラーなら0(false)、処理できたなら1、 // パケット長が足りなければ2をかえさなければならない int inter_parse_frommap(int fd) { int cmd=RFIFOW(fd,0); int len=0; // inter鯖管轄かを調べる if(cmd<0x3000 || cmd>=0x3000+( sizeof(inter_recv_packet_length)/ sizeof(inter_recv_packet_length[0]) ) ) return 0; // パケット長を調べる if( (len=inter_check_length(fd,inter_recv_packet_length[cmd-0x3000]))==0 ) return 2; switch(cmd){ case 0x3000: mapif_parse_GMmessage(fd); break; case 0x3001: mapif_parse_WisRequest(fd); break; case 0x3002: mapif_parse_WisReply(fd); break; default: if( inter_party_parse_frommap(fd) ) break; if( inter_guild_parse_frommap(fd) ) break; if( inter_storage_parse_frommap(fd) ) break; if( inter_pet_parse_frommap(fd) ) break; return 0; } RFIFOSKIP(fd, len ); return 1; }
/* * activate PIN system and set first PIN */ int chclif_parse_pincode_setnew( int fd, struct char_session_data* sd ){ if( RFIFOREST(fd) < 10 ) return 0; if( charserv_config.pincode_config.pincode_enabled==0 || RFIFOL(fd,2) != sd->account_id ) return 1; else { char newpin[PINCODE_LENGTH+1]; memset(newpin,0,PINCODE_LENGTH+1); strncpy( newpin, RFIFOCP(fd,6), PINCODE_LENGTH ); RFIFOSKIP(fd,10); char_pincode_decrypt( sd->pincode_seed, newpin ); if( pincode_allowed(newpin) ){ chlogif_pincode_notifyLoginPinUpdate( sd->account_id, newpin ); strncpy( sd->pincode, newpin, strlen( newpin ) ); chclif_pincode_sendstate( fd, sd, PINCODE_PASSED ); }else{ chclif_pincode_sendstate( fd, sd, PINCODE_ILLEGAL ); } } return 1; }
int chlogif_parse_updip(int fd, struct char_session_data* sd){ unsigned char buf[2]; uint32 new_ip = 0; WBUFW(buf,0) = 0x2b1e; chmapif_sendall(buf, 2); new_ip = host2ip(charserv_config.login_ip_str); if (new_ip && new_ip != charserv_config.login_ip) charserv_config.login_ip = new_ip; //Update login ip, too. new_ip = host2ip(charserv_config.char_ip_str); if (new_ip && new_ip != charserv_config.char_ip) { //Update ip. charserv_config.char_ip = new_ip; ShowInfo("Updating IP for [%s].\n", charserv_config.char_ip_str); // notify login server about the change WFIFOHEAD(fd,6); WFIFOW(fd,0) = 0x2736; WFIFOL(fd,2) = htonl(charserv_config.char_ip); WFIFOSET(fd,6); } RFIFOSKIP(fd,2); return 1; }
/** * Ping request from char-server to send a reply. * @param fd: fd to parse from (char-serv) * @return 1 success */ int logchrif_parse_keepalive(int fd){ RFIFOSKIP(fd,2); WFIFOHEAD(fd,2); WFIFOW(fd,0) = 0x2718; WFIFOSET(fd,2); return 1; }
/** * Set account_id to online. * @author [Wizputer] * @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_setacconline(int fd, int id){ if( RFIFOREST(fd) < 6 ) return 0; login_add_online_user(id, RFIFOL(fd,2)); RFIFOSKIP(fd,6); return 1; }
/** * Set account_id to offline. * @author [Wizputer] * @param fd: fd to parse from (char-serv) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_setaccoffline(int fd){ if( RFIFOREST(fd) < 6 ) return 0; login_remove_online_user(RFIFOL(fd,2)); RFIFOSKIP(fd,6); return 1; }
/** * 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; }
/** * Received a keepalive packet to maintain connection. * S 0204 <md5 hash>.16B (kRO 2004-05-31aSakexe langtype 0 and 6) * @param fd: fd to parse from (client fd) * @return 0 not enough info transmitted, 1 success */ static int logclif_parse_updclhash(int fd, struct login_session_data *sd){ if (RFIFOREST(fd) < 18) return 0; sd->has_client_hash = 1; memcpy(sd->client_hash, RFIFOP(fd, 2), 16); RFIFOSKIP(fd,18); return 1; }
/** * Received new charip from char-serv, update information. * @param fd: char-serv file descriptor * @param id: char-serv id * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_updcharip(int fd, int id){ if( RFIFOREST(fd) < 6 ) return 0; ch_server[id].ip = ntohl(RFIFOL(fd,2)); ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(ch_server[id].ip)); RFIFOSKIP(fd,6); return 1; }
/* * Client is requesting to move a charslot */ int chclif_parse_moveCharSlot( int fd, struct char_session_data* sd){ uint16 from, to; if( RFIFOREST(fd) < 8 ) return 0; from = RFIFOW(fd,2); to = RFIFOW(fd,4); //Cnt = RFIFOW(fd,6); //how many time we have left to change (client.. lol we don't trust him) RFIFOSKIP(fd,8); // Have we changed to often or is it disabled? if( (charserv_config.charmove_config.char_move_enabled)==0 || ( (charserv_config.charmove_config.char_moves_unlimited)==0 && sd->char_moves[from] <= 0 ) ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } // We don't even have a character on the chosen slot? if( sd->found_char[from] <= 0 || to >= sd->char_slots ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } if( sd->found_char[to] > 0 ){ // We want to move to a used position if( charserv_config.charmove_config.char_movetoused ){ // TODO: check if the target is in deletion process // Admin is friendly and uses triangle exchange if( SQL_ERROR == Sql_QueryStr(sql_handle, "START TRANSACTION") || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'",schema_config.char_db, to, sd->found_char[from] ) || SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id` = '%d'", schema_config.char_db, from, sd->found_char[to] ) || SQL_ERROR == Sql_QueryStr(sql_handle, "COMMIT") ){ chclif_moveCharSlotReply( fd, sd, from, 1 ); Sql_ShowDebug(sql_handle); Sql_QueryStr(sql_handle,"ROLLBACK"); return 1; } }else{ // Admin doesn't allow us to chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } }else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d'", schema_config.char_db, to, sd->found_char[from] ) ){ Sql_ShowDebug(sql_handle); chclif_moveCharSlotReply( fd, sd, from, 1 ); return 1; } if( (charserv_config.charmove_config.char_moves_unlimited)==0 ){ sd->char_moves[from]--; Sql_Query(sql_handle, "UPDATE `%s` SET `moves`='%d' WHERE `char_id`='%d'", schema_config.char_db, sd->char_moves[from], sd->found_char[from] ); } // We successfully moved the char - time to notify the client chclif_moveCharSlotReply( fd, sd, from, 0 ); chclif_mmo_char_send(fd, sd); return 1; }
/** * Map-serv requesting to send the list of sc_data the player has saved * @author [Skotlex] * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ int chmapif_parse_askscdata(int fd){ if (RFIFOREST(fd) < 10) return 0; else { #ifdef ENABLE_SC_SAVING int aid, cid; aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", schema_config.scdata_db, aid, cid) ) { Sql_ShowDebug(sql_handle); return 1; } if( Sql_NumRows(sql_handle) > 0 ) { struct status_change_data scdata; int count; char* data; WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); WFIFOW(fd,0) = 0x2b1d; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) { Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); } if (count >= 50) ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); if (count > 0) { WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); WFIFOW(fd,12) = count; WFIFOSET(fd,WFIFOW(fd,2)); } } else { // No Status Changes to load but still send a response WFIFOHEAD(fd,14); WFIFOW(fd,0) = 0x2b1d; WFIFOW(fd,2) = 14; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; WFIFOW(fd,12) = 0; WFIFOSET(fd,WFIFOW(fd,2)); } Sql_FreeResult(sql_handle); #endif RFIFOSKIP(fd, 10); } return 1; }
/** * AH 0x2721 * Retrieve account info from login-server, ask inter-server to tell player */ int chlogif_parse_AccInfoAck(int fd) { if (RFIFOREST(fd) < 19) return 0; else { int8 type = RFIFOB(fd, 18); if (type == 0 || RFIFOREST(fd) < 122+NAME_LENGTH) { mapif_accinfo_ack(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), 0, -1, 0, 0, NULL, NULL, NULL, NULL, NULL); RFIFOSKIP(fd,19); return 1; } type>>=1; mapif_accinfo_ack(true, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), type, RFIFOL(fd,19), RFIFOL(fd,23), RFIFOL(fd,27), RFIFOCP(fd,31), RFIFOCP(fd,71), RFIFOCP(fd,87), RFIFOCP(fd,111), RFIFOCP(fd,122)); RFIFOSKIP(fd,122+NAME_LENGTH); } return 1; }
/** * Map-serv sent us his new users count, updating info * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_getusercount(int fd, int id){ if (RFIFOREST(fd) < 4) return 0; if (RFIFOW(fd,2) != map_server[id].users) { map_server[id].users = RFIFOW(fd,2); ShowInfo("User Count: %d (Server: %d)\n", map_server[id].users, id); } RFIFOSKIP(fd, 4); return 1; }
int chlogif_parse_ack_global_accreg(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; else { //Receive account_reg2 registry, forward to map servers. RFIFOW(fd,0) = 0x3804; chmapif_sendall(RFIFOP(fd,0), RFIFOW(fd,2)); RFIFOSKIP(fd, RFIFOW(fd,2)); } return 1; }
/** * Receive a request for account data reply by sending all mmo_account information. * @param fd: fd to parse from (char-serv) * @param id: id of char-serv * @param ip: char-serv ip (used for info) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_reqaccdata(int fd, int id, char *ip){ if( RFIFOREST(fd) < 6 ) return 0; else { uint32 aid = RFIFOL(fd,2); RFIFOSKIP(fd,6); if( logchrif_send_accdata(fd,aid) < 0 ) ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", ch_server[id].name, aid, ip); } return 1; }
/** * Request from char-server to authenticate an account. * @param fd: fd to parse from (char-serv) * @param id: id of char-serv * @param ip: char-serv ip (used for info) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_reqauth(int fd, int id,char* ip){ if( RFIFOREST(fd) < 23 ) return 0; else{ struct auth_node* node; uint32 account_id = RFIFOL(fd,2); uint32 login_id1 = RFIFOL(fd,6); uint32 login_id2 = RFIFOL(fd,10); uint8 sex = RFIFOB(fd,14); //uint32 ip_ = ntohl(RFIFOL(fd,15)); int request_id = RFIFOL(fd,19); RFIFOSKIP(fd,23); node = (struct auth_node*)idb_get(auth_db, account_id); if( runflag == LOGINSERVER_ST_RUNNING && node != NULL && node->account_id == account_id && node->login_id1 == login_id1 && node->login_id2 == login_id2 && node->sex == sex_num2str(sex) /*&& node->ip == ip_*/ ){// found //ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip); // send ack WFIFOHEAD(fd,21); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; WFIFOL(fd,6) = login_id1; WFIFOL(fd,10) = login_id2; WFIFOB(fd,14) = sex; WFIFOB(fd,15) = 0;// ok WFIFOL(fd,16) = request_id; WFIFOB(fd,20) = node->clienttype; WFIFOSET(fd,21); // each auth entry can only be used once idb_remove(auth_db, account_id); }else{// authentication not found ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", ch_server[id].name, account_id, ip); WFIFOHEAD(fd,21); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; WFIFOL(fd,6) = login_id1; WFIFOL(fd,10) = login_id2; WFIFOB(fd,14) = sex; WFIFOB(fd,15) = 1;// auth failed WFIFOL(fd,16) = request_id; WFIFOB(fd,20) = 0; WFIFOSET(fd,21); } } return 1; }
/** * Player Requesting char-select from map_serv * @param fd: wich fd to parse from * @return : 0 not enough data received, 1 success */ int chmapif_parse_authok(int fd){ if( RFIFOREST(fd) < 19 ) return 0; else{ uint32 account_id = RFIFOL(fd,2); uint32 login_id1 = RFIFOL(fd,6); uint32 login_id2 = RFIFOL(fd,10); uint32 ip = RFIFOL(fd,14); int version = RFIFOB(fd,18); RFIFOSKIP(fd,19); if( runflag != CHARSERVER_ST_RUNNING ){ WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x2b03; WFIFOL(fd,2) = account_id; WFIFOB(fd,6) = 0;// not ok WFIFOSET(fd,7); }else{ struct auth_node* node; DBMap* auth_db = char_get_authdb(); DBMap* online_char_db = char_get_onlinedb(); // create temporary auth entry CREATE(node, struct auth_node, 1); node->account_id = account_id; node->char_id = 0; node->login_id1 = login_id1; node->login_id2 = login_id2; //node->sex = 0; node->ip = ntohl(ip); node->version = version; //upd version for mapserv //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) //node->gmlevel = 0; idb_put(auth_db, account_id, node); //Set char to "@ char select" in online db [Kevin] char_set_charselect(account_id); { struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id); if( character != NULL ){ character->pincode_success = true; } } WFIFOHEAD(fd,7); WFIFOW(fd,0) = 0x2b03; WFIFOL(fd,2) = account_id; WFIFOB(fd,6) = 1;// ok WFIFOSET(fd,7); } } return 1; }
/** * Map-serv request to save mmo_char_status in sql * Receive character data from map-server for saving * @param fd: wich fd to parse from * @param id: wich map_serv id * @return : 0 not enough data received, 1 success */ int chmapif_parse_reqsavechar(int fd, int id){ if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; { int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); struct online_char_data* character; DBMap* online_char_db = char_get_onlinedb(); if (size - 13 != sizeof(struct mmo_charstatus)) { ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus)); RFIFOSKIP(fd,size); return 1; } //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect if (RFIFOB(fd,12) || RFIFOB(fd,13) || ( (character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL && character->char_id == cid)) { struct mmo_charstatus char_dat; memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus)); char_mmo_char_tosql(cid, &char_dat); } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off. ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid); char_set_char_online(id, cid, aid); } if (RFIFOB(fd,12)) { //Flag, set character offline after saving. [Skotlex] char_set_char_offline(cid, aid); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save. WFIFOL(fd,2) = aid; WFIFOL(fd,6) = cid; WFIFOSET(fd,10); } RFIFOSKIP(fd,size); } return 1; }
/** * Request account_reg2 for a character. * @param fd: fd to parse from (char-serv) * @return 0 not enough info transmitted, 1 success */ int logchrif_parse_req_global_accreg(int fd){ if (RFIFOREST(fd) < 10) return 0; else{ AccountDB* accounts = login_get_accounts_db(); uint32 account_id = RFIFOL(fd,2); uint32 char_id = RFIFOL(fd,6); RFIFOSKIP(fd,10); mmo_send_global_accreg(accounts,fd,account_id,char_id); } return 1; }