int32 parse(int8* buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data) { // начало обработки входящего пакета int8* PacketData_Begin = &buff[FFXI_HEADER_SIZE]; int8* PacketData_End = &buff[*buffsize]; CCharEntity *PChar = map_session_data->PChar; uint16 SmallPD_Size = 0; uint16 SmallPD_Type = 0; uint16 SmallPD_Code = RBUFW(buff,0); for(int8* SmallPD_ptr = PacketData_Begin; SmallPD_ptr + (RBUFB(SmallPD_ptr,1) & 0xFE)*2 <= PacketData_End && (RBUFB(SmallPD_ptr,1) & 0xFE); SmallPD_ptr = SmallPD_ptr + SmallPD_Size*2) { SmallPD_Size = (RBUFB(SmallPD_ptr,1) & 0x0FE); SmallPD_Type = (RBUFW(SmallPD_ptr,0) & 0x1FF); if(PacketSize[SmallPD_Type] == SmallPD_Size || PacketSize[SmallPD_Type] == 0) // Tests incoming packets for the correct size prior to processing { // если код текущего пакета меньше либо равен последнему полученному // или больше глобального то игнорируем пакет if ((RBUFW(SmallPD_ptr,2) <= map_session_data->client_packet_id) || (RBUFW(SmallPD_ptr,2) > SmallPD_Code)) { continue; } if (SmallPD_Type != 0x15) { ShowInfo("parse: %03hX | %04hX %04hX %02hX from user: %s\n", SmallPD_Type, RBUFW(SmallPD_ptr,2), RBUFW(buff,2), SmallPD_Size, PChar->GetName()); } if (PChar->loc.zone == NULL && SmallPD_Type != 0x0A) { ShowWarning("This packet is unexpected from %s - Received %03hX earlier without matching 0x0A\n", PChar->GetName(), SmallPD_Type); } else { PacketParser[SmallPD_Type](map_session_data, PChar, SmallPD_ptr); } } else { ShowWarning("Bad packet size %03hX | %04hX %04hX %02hX from user: %s\n", SmallPD_Type, RBUFW(SmallPD_ptr,2), RBUFW(buff,2), SmallPD_Size, PChar->GetName()); } } map_session_data->client_packet_id = SmallPD_Code; // здесь мы проверяем, получил ли клиент предыдущий пакет // если не получил, то мы не создаем новый, а отправляем предыдущий if (RBUFW(buff,2) != map_session_data->server_packet_id) { WBUFW(map_session_data->server_packet_data,2) = SmallPD_Code; WBUFW(map_session_data->server_packet_data,8) = (uint32)time(NULL); g_PBuff = map_session_data->server_packet_data; *buffsize = map_session_data->server_packet_size; map_session_data->server_packet_data = buff; return -1; } // увеличиваем номер отправленного пакета только в случае отправки новых данных map_session_data->server_packet_id += 1; // собираем большой пакет, состоящий из нескольких маленьких CBasicPacket* PSmallPacket; *buffsize = FFXI_HEADER_SIZE; while(!PChar->isPacketListEmpty() && *buffsize + PChar->firstPacketSize()*2 < map_config.buffer_size ) { PSmallPacket = PChar->popPacket(); PSmallPacket->setCode(map_session_data->server_packet_id); memcpy(buff+*buffsize, PSmallPacket, PSmallPacket->getSize()*2); *buffsize += PSmallPacket->getSize()*2; delete PSmallPacket; } return 0; }