int32 CTCPRequestPacket::SendToSocket(uint8* data, uint32 length) { int32 iResult; WBUFW(data,(0x00)) = length; // packet size WBUFL(data,(0x04)) = 0x46465849; // "XIFF" md5((uint8*)(key), blowfish.hash, 24); blowfish_init((int8*)blowfish.hash,16, blowfish.P, blowfish.S[0]); md5(data+8, data+length-0x18+0x04, length-0x18-0x04); uint8 tmp = (length-12)/4; tmp -= tmp%2; for(uint8 i = 0; i < tmp; i += 2) { blowfish_encipher((uint32*)data+i+2, (uint32*)data+i+3, blowfish.P, blowfish.S[0]); } memcpy(&data[length]-0x04, key+16, 4); iResult = send(*m_socket, (const int8*)data, length, 0); if (iResult == SOCKET_ERROR) { ShowError("send failed with error: %d\n", WSAGetLastError()); return 0; } return ReceiveFromSocket(); }
//Party map update notification int mapif_party_membermoved(struct party *p, int idx) { unsigned char buf[20]; nullpo_ret(p); Assert_ret(idx >= 0 && idx < MAX_PARTY); WBUFW(buf,0) = 0x3825; WBUFL(buf,2) = p->party_id; WBUFL(buf,6) = p->member[idx].account_id; WBUFL(buf,10) = p->member[idx].char_id; WBUFW(buf,14) = p->member[idx].map; WBUFB(buf,16) = p->member[idx].online; WBUFW(buf,17) = p->member[idx].lv; mapif->sendall(buf, 19); return 0; }
// Party setting change notification int mapif_party_optionchanged(int fd, struct party *p, int account_id, int flag) { unsigned char buf[16]; nullpo_ret(p); WBUFW(buf,0)=0x3823; WBUFL(buf,2)=p->party_id; WBUFL(buf,6)=account_id; WBUFW(buf,10)=p->exp; WBUFW(buf,12)=p->item; WBUFB(buf,14)=flag; if(flag==0) mapif->sendall(buf,15); else mapif->send(fd,buf,15); return 0; }
CFadeOutPacket::CFadeOutPacket(CBaseEntity * PEntity) { this->type = 0x38; this->size = 0x0A; WBUFL(data,(0x04)-4) = PEntity->id; WBUFL(data,(0x08)-4) = PEntity->id; WBUFB(data,(0x0C)-4) = 0x6b; WBUFB(data,(0x0D)-4) = 0x65; WBUFB(data,(0x0E)-4) = 0x73; WBUFB(data,(0x0F)-4) = 0x75; WBUFW(data,(0x10)-4) = PEntity->targid; WBUFW(data,(0x12)-4) = PEntity->targid; }
int32 CTCPRequestPacket::ReceiveFromSocket() { int8 recvbuf[DEFAULT_BUFLEN]; m_size = recv(*m_socket, recvbuf, DEFAULT_BUFLEN, 0); if (m_size == -1) { ShowError(CL_RED"recv failed with error: %d\n" CL_RESET, WSAGetLastError()); return 0; } if (m_size == 0) { //ShowError("TCP Connection closing...\n"); return 0; } if (m_size != RBUFW(recvbuf,(0x00)) || m_size < 28) { ShowError(CL_RED"Search packetsize wrong. Size %d should be %d.\n" CL_RESET, m_size, RBUFW(recvbuf,(0x00))); return 0; } delete[] m_data; m_data = new uint8[m_size]; memcpy(&m_data[0], &recvbuf[0], m_size); WBUFL(key,(16)) = RBUFL(m_data,(m_size-4)); return decipher(); }
void CQuestMissionLogPacket::generateCurrentMissionPacket(CCharEntity * PChar) { uint16 add_on_scenarios = 0; add_on_scenarios += PChar->m_missionLog[MISSION_ACP].current; add_on_scenarios += PChar->m_missionLog[MISSION_AMK].current << 0x04; add_on_scenarios += PChar->m_missionLog[MISSION_ASA].current << 0x08; // Not perfect, but they display and missions DO progress. Can fix properly later. There is a delay before when the menu updates. Zoning will force it. uint32 chains = 0; chains = PChar->m_missionLog[MISSION_COP].current + 1; chains = ((chains * 0x08) + 0x60); uint32 soa = (PChar->m_missionLog[MISSION_SOA].current * 2) + 0x6E; uint32 rov = PChar->m_missionLog[MISSION_ROV].current + 0x6C; // While current National Missions + Zilart Mission are updated in this packet, completed missions are sent in a separate one. WBUFB(data, (0x04)) = PChar->profile.nation; // Nation WBUFW(data, (0x08)) = PChar->m_missionLog[PChar->profile.nation].current; // National Missions WBUFW(data, (0x0C)) = PChar->m_missionLog[MISSION_ZILART].current; // Rise of the Zilart // But for COP, Add-On Scenarios, SOA, and ROV, sending the current mission will also update that log's completed missions. WBUFL(data, (0x10)) = chains; // Chains of Promathia Missions //WBUFB(data,(0x16)) = 0x30; // назначение неизвестно WBUFW(data, (0x18)) = add_on_scenarios; // A Crystalline Prophecy, A Moogle Kupo d'Etat, A Shantotto Ascension WBUFW(data, (0x1C)) = soa; // Seekers of Adoulin WBUFW(data, (0x20)) = rov; // Rhapsodies of Vana'diel }
void CParty::AddMember(uint32 id) { if (m_PartyType == PARTY_PCS) { uint32 allianceid = 0; if (m_PAlliance) { allianceid = m_PAlliance->m_AllianceID; } Sql_Query(SqlHandle, "INSERT INTO accounts_parties (charid, partyid, allianceid, partyflag) VALUES (%u, %u, %u, %u);", id, m_PartyID, allianceid, 0); uint8 data[4]; WBUFL(data, 0) = m_PartyID; message::send(MSG_PT_RELOAD, data, sizeof data, nullptr); /*if (PChar->nameflags.flags & FLAG_INVITE) { PChar->nameflags.flags ^= FLAG_INVITE; PChar->updatemask |= UPDATE_HP; charutils::SaveCharStats(PChar); PChar->status = STATUS_UPDATE; PChar->pushPacket(new CMenuConfigPacket(PChar)); PChar->pushPacket(new CCharUpdatePacket(PChar)); PChar->pushPacket(new CCharSyncPacket(PChar)); } PChar->PTreasurePool->UpdatePool(PChar);*/ } }
/** * Send to map-servers the users count on this char-serv, (meaning the total of all mapserv) * @param users: number of players on this char-serv */ void chmapif_sendall_playercount(int users){ uint8 buf[6]; // send number of players to all map-servers WBUFW(buf,0) = 0x2b00; WBUFL(buf,2) = users; chmapif_sendall(buf,6); }
CTreasureFindItemPacket::CTreasureFindItemPacket(TreasurePoolItem* PItem , CBaseEntity* PMob) { this->type = 0xD2; this->size = 0x1E; WBUFL(data,(0x04)-4) = 1; // ItemQuantity, а вожможен размер, отличный от единицы, исключая gil ??? WBUFW(data,(0x10)-4) = PItem->ID; // ItemID WBUFB(data,(0x14)-4) = PItem->SlotID; // TreasurePool slotID WBUFL(data,(0x18)-4) = PItem->TimeStamp; // TimeStamp if (PMob != nullptr) { WBUFL(data,(0x08)-4) = PMob->id; // ID монстра WBUFW(data,(0x12)-4) = PMob->targid; // TargID монстра } }
int chlogif_broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) { uint8 buf[6]; int users = char_count_users(); // only send an update when needed static int prev_users = 0; if( prev_users == users ) return 0; prev_users = users; if( chlogif_isconnected() ) { // send number of user to login server WFIFOHEAD(login_fd,6); WFIFOW(login_fd,0) = 0x2714; WFIFOL(login_fd,2) = users; WFIFOSET(login_fd,6); } // send number of players to all map-servers WBUFW(buf,0) = 0x2b00; WBUFL(buf,2) = users; chmapif_sendall(buf,6); return 0; }
/** * 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; }
CMessageStandardPacket::CMessageStandardPacket(CCharEntity* PChar, uint32 param0, uint32 param1, uint16 MessageID) { this->type = 0x09; this->size = 0x12; WBUFW(data,(0x0A)-4) = MessageID; if (PChar != nullptr) { WBUFL(data,(0x04)-4) = PChar->id; WBUFW(data,(0x08)-4) = PChar->targid; if (MessageID == 0x59) { this->size = 0x30; WBUFB(data,(0x0C)-4) = 0x10; snprintf((int8*)data+(0x0D)-4, 24, "string2 %s", PChar->GetName()); } } else { snprintf((int8*)data+(0x0D)-4, 20, "Para0 %d Para1 %d", param0, param1); } }
// パーティ設定変更通知 int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag) { unsigned char buf[16]; WBUFW(buf,0)=0x3823; WBUFL(buf,2)=p->party_id; WBUFL(buf,6)=account_id; WBUFW(buf,10)=p->exp; WBUFW(buf,12)=p->item; WBUFB(buf,14)=flag; if(flag==0) mapif_sendall(buf,15); else mapif_send(fd,buf,15); printf("int_party: option changed %d %d %d %d %d\n",p->party_id,account_id,p->exp,p->item,flag); return 0; }
CShopItemsPacket::CShopItemsPacket(CCharEntity * PChar) { this->type = 0x3C; this->size = 0x04; uint8 ItemsCount = PChar->Container->getItemsCount(); uint8 i = 0; for (uint8 slotID = 0; slotID < ItemsCount; ++slotID) { if (i == 20) { PChar->pushPacket(new CBasicPacket(*this)); i = 0; this->size = 0x04; memset(data, 0, sizeof(data)); } this->size += 0x06; WBUFL(data,((i*12)+0x08)-4) = PChar->Container->getQuantity(slotID); WBUFW(data,((i*12)+0x0C)-4) = PChar->Container->getItemID(slotID); WBUFB(data,((i*12)+0x0E)-4) = slotID; i++; } }
CShopBuyPacket::CShopBuyPacket(uint8 slotID, uint32 quantity) { this->type = 0x3F; this->size = 0x06; WBUFB(data,(0x04)-4) = slotID; WBUFL(data,(0x08)-4) = quantity; }
CWeatherPacket::CWeatherPacket(uint32 ChangeTime, WEATHER WeatherEffect) { this->type = 0x57; this->size = 0x06; WBUFL(data,(0x04)-4) = ChangeTime; WBUFW(data,(0x08)-4) = WeatherEffect; }
CMeritPointsCategoriesPacket::CMeritPointsCategoriesPacket(CCharEntity* PChar, MERIT_TYPE merit) { this->type = 0x8C; this->size = 0x08; WBUFB(data,(0x04)-4) = 1; WBUFL(data,(0x08)-4) = PChar->PMeritPoints->GetMerit(merit)->data; }
CShopAppraisePacket::CShopAppraisePacket(uint8 slotID, uint32 sellPrice) { this->type = 0x3D; this->size = 0x08; WBUFL(data,(0x04)) = sellPrice; WBUFB(data,(0x08)) = slotID; }
CMessageDebugPacket::CMessageDebugPacket(CBaseEntity* PSender, CBaseEntity* PTarget, int32 param0, int32 param1, uint16 messageID) { this->type = 0x2d; this->size = 0x0e; WBUFL(data,(0x04)) = PSender->id; WBUFL(data,(0x08)) = PTarget->id; WBUFW(data,(0x0C)) = PSender->targid; WBUFW(data,(0x0E)) = PTarget->targid; WBUFL(data,(0x10)) = param0; WBUFL(data,(0x14)) = param1; WBUFW(data,(0x18)) = messageID; //WBUFB(data,(0x1A)) = 0x01; }
int chlogif_parse_accbannotification(int fd, struct char_session_data* sd){ if (RFIFOREST(fd) < 11) return 0; { // send to all map-servers to disconnect the player unsigned char buf[11]; WBUFW(buf,0) = 0x2b14; WBUFL(buf,2) = RFIFOL(fd,2); WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment chmapif_sendall(buf, 11); } // disconnect player if online on char-server char_disconnect_player(RFIFOL(fd,2)); RFIFOSKIP(fd,11); return 1; }
// 脱退/追放通知 int mapif_guild_withdraw(int guild_id, int account_id, int char_id, int flag, const char *name, const char *mes) { unsigned char buf[79]; WBUFW(buf, 0) = 0x3834; WBUFL(buf, 2) = guild_id; WBUFL(buf, 6) = account_id; WBUFL(buf,10) = char_id; WBUFB(buf,14) = flag; memcpy(WBUFP(buf,15), mes, 40); memcpy(WBUFP(buf,55), name, NAME_LENGTH); mapif_sendall(buf, 55+NAME_LENGTH); // mapif_sendall(buf, 79); ShowInfo("Character left guild (Guild %d, %d - %s: %s)\n", guild_id, account_id, name, mes); return 0; }
/** * Send to map-servers the updated fame ranking lists * We actually just send this one when we only need to update rankpoint but pos didn't change * @param type: ranking type * @param index: position in the ranking * @param fame: number of points */ void chmapif_update_fame_list(int type, int index, int fame) { unsigned char buf[8]; WBUFW(buf,0) = 0x2b22; WBUFB(buf,2) = type; WBUFB(buf,3) = index; WBUFL(buf,4) = fame; chmapif_sendall(buf, 8); }
CServerMessagePacket::CServerMessagePacket(const string_t message, int8 language, int32 timestamp, int32 message_offset) { this->type = 0x4D; this->size = 0x0E; WBUFB(data, (0x04) ) = message_offset == 0 ? 1 : 2; WBUFB(data, (0x05) ) = 1; WBUFB(data, (0x06) ) = 1; WBUFB(data, (0x07) ) = language; WBUFL(data, (0x08) ) = timestamp == 0 ? time(0) : timestamp; WBUFL(data, (0x0C) ) = 0; // Message Length.. (Total) WBUFL(data, (0x10) ) = 0; // Message Offset.. WBUFL(data, (0x14) ) = 0; // Message Length.. // Ensure we have a message and the requested offset is not outside of the bounds.. if (message.length() > 0 && message.length() > message_offset) { int32 msgLength = message.length(); int32 sndLength = (msgLength - message_offset) > 236 ? 236 : (msgLength - message_offset); WBUFL(data, (0x0C) ) = message.length(); // Message Length.. (Total) WBUFL(data, (0x10) ) = message_offset; // Message Offset.. WBUFL(data, (0x14) ) = sndLength; // Message Length.. memcpy((data + (0x18)) , message.c_str() + message_offset, sndLength); int32 textSize = sndLength + sndLength % 2; this->size = ((((0x14 + textSize) + 4) >> 1) & 0xFE); }
/** * Receiving a ban request from map-server via char-server. * @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 * TODO check logchrif_parse_requpdaccstate for possible merge */ int logchrif_parse_reqbanacc(int fd, int id, char* ip){ if (RFIFOREST(fd) < 10) return 0; else{ struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); uint32 account_id = RFIFOL(fd,2); int timediff = RFIFOL(fd,6); RFIFOSKIP(fd,10); if( !accounts->load_num(accounts, &acc, account_id) ) ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip); else{ time_t timestamp; if (acc.unban_time == 0 || acc.unban_time < time(NULL)) timestamp = time(NULL); // new ban else timestamp = acc.unban_time; // add to existing ban timestamp += timediff; if (timestamp == -1) ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", ch_server[id].name, account_id, ip); else if( timestamp <= time(NULL) || timestamp == 0 ) ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", ch_server[id].name, account_id, ip); else{ uint8 buf[11]; char tmpstr[24]; timestamp2string(tmpstr, sizeof(tmpstr), timestamp, login_config.date_format); ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", ch_server[id].name, account_id, timestamp, tmpstr, ip); acc.unban_time = timestamp; // Save accounts->save(accounts, &acc); WBUFW(buf,0) = 0x2731; WBUFL(buf,2) = account_id; WBUFB(buf,6) = 1; // 0: change of status, 1: ban WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment logchrif_sendallwos(-1, buf, 11); } } } return 1; }
// ギルド同盟/敵対通知 int mapif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag, const char *name1, const char *name2) { unsigned char buf[67]; WBUFW(buf, 0) = 0x383d; WBUFL(buf, 2) = guild_id1; WBUFL(buf, 6) = guild_id2; WBUFL(buf,10) = account_id1; WBUFL(buf,14) = account_id2; WBUFB(buf,18) = flag; memcpy(WBUFP(buf,19), name1, NAME_LENGTH); memcpy(WBUFP(buf,19+NAME_LENGTH), name2, NAME_LENGTH); mapif_sendall(buf,19+2*NAME_LENGTH); /* memcpy(WBUFP(buf,43), name2, NAME_LENGTH); mapif_sendall(buf, 67); */ return 0; }
void CParty::AddMember(CBattleEntity* PEntity, Sql_t* sql) { DSP_DEBUG_BREAK_IF(PEntity == NULL); DSP_DEBUG_BREAK_IF(PEntity->PParty != NULL); PEntity->PParty = this; members.push_back(PEntity); if (m_PartyType == PARTY_PCS) { DSP_DEBUG_BREAK_IF(PEntity->objtype != TYPE_PC); CCharEntity* PChar = (CCharEntity*)PEntity; uint32 allianceid = 0; if (m_PAlliance) { allianceid = m_PAlliance->m_AllianceID; } Sql_Query(sql, "INSERT INTO accounts_parties (charid, partyid, allianceid, partyflag) VALUES (%u, %u, %u, %u);", PChar->id, m_PartyID, allianceid, GetMemberFlags(PChar)); uint8 data[4]; WBUFL(data, 0) = m_PartyID; message::send(MSG_PT_RELOAD, data, sizeof data, NULL); ReloadTreasurePool(PChar); if (PChar->nameflags.flags & FLAG_INVITE) { PChar->nameflags.flags ^= FLAG_INVITE; charutils::SaveCharStats(PChar); PChar->status = STATUS_UPDATE; PChar->pushPacket(new CMenuConfigPacket(PChar)); PChar->pushPacket(new CCharUpdatePacket(PChar)); PChar->pushPacket(new CCharSyncPacket(PChar)); } PChar->PTreasurePool->UpdatePool(PChar); //Apply level sync if the party is level synced if (m_PSyncTarget != NULL) { if (PChar->getZone() == m_PSyncTarget->getZone() ) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, m_PSyncTarget->GetMLevel(), 540)); PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect( EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, m_PSyncTarget->GetMLevel(), 0, 0), true); PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE | EFFECTFLAG_ON_ZONE); PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE, new CCharSyncPacket(PChar)); } } } }
CInventoryModifyPacket::CInventoryModifyPacket(uint8 LocationID, uint8 slotID, uint32 quantity) { this->type = 0x1E; this->size = 0x08; WBUFL(data,(0x04)) = quantity; WBUFB(data,(0x08)) = LocationID; WBUFB(data,(0x09)) = slotID; }
CServerIPPacket::CServerIPPacket(CCharEntity* PChar, uint8 type) { this->type = 0x0B; this->size = 0x0E; WBUFB(data,(0x04)-4) = type; WBUFL(data,(0x08)-4) = PChar->loc.zone->GetIP(); WBUFW(data,(0x0C)-4) = PChar->loc.zone->GetPort(); }
CCaughtFishPacket::CCaughtFishPacket(CCharEntity * PChar, uint16 param0, uint16 messageID) { this->type = 0x27; this->size = 0x38; //DSP_DEBUG_BREAK_IF(PChar->name.size() > 15); WBUFL(data,(0x04)) = PChar->id; WBUFL(data,(0x08)) = PChar->targid; WBUFW(data,(0x0A)) = messageID + 0x8000; WBUFW(data,(0x10)) = param0; WBUFL(data,(0x14)) = 0x01; WBUFL(data,(0x1C)) = 0xF0; memcpy(data+(0x20), PChar->GetName(), PChar->name.size()); }
CChocoboDiggingPacket::CChocoboDiggingPacket(CCharEntity* PChar) { this->type = 0x2F; this->size = 0x06; WBUFL(data,(0x04)-4) = PChar->id; WBUFW(data,(0x08)-4) = PChar->targid; WBUFB(data,(0x0A)-4) = 0x01; }