Beispiel #1
0
/// Dumps given buffer into file pointed to by a handle.
void WriteDump(FILE* fp, const void* buffer, size_t length)
{
	size_t i;
	char hex[48+1], ascii[16+1];

	fprintf(fp, "--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F   0123456789ABCDEF\n");
	ascii[16] = 0;

	for( i = 0; i < length; i++ )
	{
		char c = RBUFB(buffer,i);

		ascii[i%16] = ISCNTRL(c) ? '.' : c;
		sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));

		if( (i%16) == 15 )
		{
			fprintf(fp, "%03X %s  %s\n", (unsigned int)(i/16), hex, ascii);
		}
	}

	if( (i%16) != 0 )
	{
		ascii[i%16] = 0;
		fprintf(fp, "%03X %-48s  %-16s\n", (unsigned int)(i/16), hex, ascii);
	}
}
Beispiel #2
0
/// Dumps given buffer on the console.
void ShowDump(const void* buffer, size_t length)
{
	size_t i;
	char hex[48+1], ascii[16+1];

	ShowDebug("--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F   0123456789ABCDEF\n");
	ascii[16] = 0;

	for( i = 0; i < length; i++ )
	{
		char c = RBUFB(buffer,i);

		ascii[i%16] = ISCNTRL(c) ? '.' : c;
		sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));

		if( (i%16) == 15 )
		{
			ShowDebug("%03X %s  %s\n", i/16, hex, ascii);
		}
	}

	if( (i%16) != 0 )
	{
		ascii[i%16] = 0;
		ShowDebug("%03X %-48s  %-16s\n", i/16, hex, ascii);
	}
}
Beispiel #3
0
CCharEmotionPacket::CCharEmotionPacket(CCharEntity * PChar, int8* buff) 
{
	this->type = 0x5a;
	this->size = 0x0c;
	
	WBUFL(data,(0x04)-4) = PChar->id;
	WBUFW(data,(0x0C)-4) = PChar->targid;

	
	WBUFL(data,(0x08)-4) = RBUFL(buff,(0x04));
	WBUFW(data,(0x0E)-4) = RBUFW(buff,(0x08));

	uint8 emoteID = RBUFB(buff,(0x0A));

	if (emoteID == 0x4A) {
		uint8 offset = RBUFB(buff,(0x0C)) - 0x1F;

		WBUFB(data,(0x10)-4) = emoteID + offset; 
		WBUFB(data,(0x12)-4) = offset; 
	}else{
		WBUFB(data,(0x10)-4) = emoteID;

		CItem * weapon = PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_MAIN]);
		if (weapon != NULL && weapon->getID() != 0xFFFF) {
			WBUFW(data,(0x12)-4) = weapon->getID();
		}
	}

	WBUFB(data,(0x16)-4) = RBUFB(buff,(0x0B));
}
Beispiel #4
0
CAddtoEquipSet::CAddtoEquipSet(int8* orig)
{
	//Im guessing this is here to check if you can use A Item, as it seems useless to have this sent to server
	//as It will check requirements when it goes to equip the items anyway
	//0x04 is slot of updated item
	//0x08 is info for updated item
	//0x0C is first slot every 4 bytes is another set, in (01-equip 0-2 remve),(container),(ID),(ID)
	//in this list the slot of whats being updated is old value, replace with new in 116
	//Should Push 0x116 (size 68) in responce
	//0x04 is start, contains 16 4 byte parts repersently each slot in order
	this->type = 0x16;
	this->size = 0x23;
	uint8 slotID = RBUFB(orig, 0x04);
	for (int i = 0; i < 0x10; i++)
	{
		if (i == slotID)
		{
			WBUFB(data, (0x04) + (0x04 * i) ) = RBUFB(orig, 0x08);
			WBUFB(data, (0x05) + (0x04 * i) ) = RBUFB(orig, 0x09);
			WBUFB(data, (0x06) + (0x04 * i) ) = RBUFB(orig, 0x0A);
			WBUFB(data, (0x07) + (0x04 * i) ) = RBUFB(orig, 0x0B);
		}
		else
		{
			WBUFB(data, (0x04) + (0x04 * i) ) = RBUFB(orig, 0x0C + (0x04 * i));
			WBUFB(data, (0x05) + (0x04 * i) ) = RBUFB(orig, 0x0D + (0x04 * i));
			WBUFB(data, (0x06) + (0x04 * i) ) = RBUFB(orig, 0x0E + (0x04 * i));
			WBUFB(data, (0x07) + (0x04 * i) ) = RBUFB(orig, 0x0F + (0x04 * i));
		}
	}
}
Beispiel #5
0
void HandleAuctionHouseRequest(CTCPRequestPacket* PTCPRequest)
{
    uint8* data    = (uint8*)PTCPRequest->GetData();                            
	uint8  AHCatID = RBUFB(data,(0x16));

    //2 - уровень -- level
    //3 - раса -- race
    //4 - профессия -- job
    //5 - урон -- damage
    //6 - задержка -- delay
    //7 - защита -- defense
    //8 - сопротивление -- resistance
    //9 - название -- name
	string_t OrderByString = "ORDER BY";
	uint8 paramCount = RBUFB(data,0x12);
    for (uint8 i = 0; i < paramCount; ++i) // параметры сортировки предметов
    {
		uint8 param = RBUFL(data,(0x18)+8*i);
        ShowMessage(" Param%u: %u\n", i, param);
		switch (param) {
			case 2:
				OrderByString.append(" item_armor.level DESC,");
			case 5:
				OrderByString.append(" item_weapon.dmg DESC,");
			case 6:
				OrderByString.append(" item_weapon.delay DESC,");
			case 9:
				OrderByString.append(" item_basic.sortname,");
		}
    }

	OrderByString.append(" item_basic.itemid");
	int8* OrderByArray = (int8*)OrderByString.data();

	CDataLoader* PDataLoader = new CDataLoader();                        
    std::vector<ahItem*> ItemList = PDataLoader->GetAHItemsToCategory(AHCatID,OrderByArray);

    uint8 PacketsCount = (ItemList.size() / 20) + (ItemList.size() % 20 != 0) + (ItemList.size() == 0);

    for(uint8 i = 0; i < PacketsCount; ++i) 
    {
        CAHItemsListPacket* PAHPacket = new CAHItemsListPacket(20*i);

        PAHPacket->SetItemCount(ItemList.size());  

        for (uint16 y = 20*i; (y != 20*(i+1)) && (y < ItemList.size()); ++y)
        {
            PAHPacket->AddItem(ItemList.at(y));
        }

        PTCPRequest->SendToSocket(PAHPacket->GetData(), PAHPacket->GetSize());
        delete PAHPacket;
    }
    delete PDataLoader;
}
Beispiel #6
0
void HandleAuctionHouseHistoru(CTCPRequestPacket* PTCPRequest)
{
    uint8* data   = (uint8*)PTCPRequest->GetData();                            
	uint16 ItemID = RBUFW(data,(0x12));
    uint8  stack  = RBUFB(data,(0x15));

	CAHHistoryPacket* PAHPacket = new CAHHistoryPacket(ItemID);

    CDataLoader* PDataLoader = new CDataLoader();
    std::vector<ahHistory*> HistoryList = PDataLoader->GetAHItemHystory(ItemID, stack != 0);

	for (uint8 i = 0; i < HistoryList.size(); ++i)
	{
		PAHPacket->AddItem(HistoryList.at(i));
	}

    PTCPRequest->SendToSocket(PAHPacket->GetData(), PAHPacket->GetSize());

    delete PDataLoader;
    delete PAHPacket;
}
Beispiel #7
0
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 == nullptr && 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, CBasicPacket(reinterpret_cast<uint8*>(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());
        }
    }
    ((CAICharNormal*)PChar->PBattleAI)->CheckActionAfterReceive(gettick());
    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(nullptr);

        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;

    return 0;
}
Beispiel #8
0
	void EmptyHandler(session_data_t* session, CPlayer* PPlayer, int8* data)
	{
		ShowWarning(CL_YELLOW"packet parser: unhandled packet %02hX from username %s\n" CL_RESET, RBUFB(data, 0), PPlayer->GetName());
	}
Beispiel #9
0
search_req _HandleSearchRequest(CTCPRequestPacket* PTCPRequest, SOCKET socket)
{
	// суть в том, чтобы заполнить некоторую структуру, на основании которой будет создан запрос к базе
	// результат поиска в базе отправляется клиенту

	uint32 bitOffset = 0;

	unsigned char sortDescending = 0;
	unsigned char isPresent = 0;
	unsigned char areaCount = 0;

	uint8 name[16];
	uint8 nameLen = 0;
	uint8 minLvl = 0;
	uint8 maxLvl = 0;
	uint8 jobid = 0;
    uint16 areas[10];

	uint8* data = (uint8*)PTCPRequest->GetData();
	uint8  size = RBUFB(data,(0x10));

	uint16 workloadBits = size * 8;

    memset(areas, 0, sizeof(areas));
	//ShowMessage("Received a search packet with size %u byte\n", size);
	
	while(bitOffset < workloadBits)
	{
		if ((bitOffset+5) >= workloadBits)
		{
			bitOffset = workloadBits;
			break;
		}

		uint8 EntryType = (uint8)unpackBitsLE(&data[0x11], bitOffset, 5);
		bitOffset+=5;

		if ((EntryType != SEARCH_FRIEND) &&
			(EntryType != SEARCH_LINKSHELL) &&
			(EntryType != SEARCH_COMMENT) &&
			(EntryType != SEARCH_FLAGS2))		
		{
			if ((bitOffset+3) >= workloadBits) //so 0000000 at the end does not get interpretet as name entry ...
			{
				bitOffset=workloadBits;
				break;
			}
			sortDescending = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,1);
			bitOffset+=1;

			isPresent = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,1);
			bitOffset+=1;
		}

		switch(EntryType)
		{
			case SEARCH_NAME:
			{
				if (isPresent==0x1) //Name send
				{
					if ((bitOffset+5) >= workloadBits)
					{
						bitOffset=workloadBits;
						break;
					}
					nameLen = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,5);
					name[nameLen]='\0';
					
					bitOffset+=5;

					for (unsigned char i = 0; i < nameLen; i++)
					{
						name[i] = (char)unpackBitsLE(&data[0x11],bitOffset,7);
						bitOffset+=7;
					}	
					//printf("SEARCH::Name Entry Found. (%s).\n",name);
				}
				//printf("SEARCH::SortByName: %s.\n",(sortDescending == 0 ? "ascending" : "descending"));
				//packetData.sortDescendingByName=sortDescending;
				break;
			}			
			case SEARCH_AREA: //Area Code Entry - 10 bit
			{
				if (isPresent == 0) //no more Area entries
				{
					//printf("SEARCH::Area List End found.\n");
				}
				else // 8 Bit = 1 Byte per Area Code
				{
					areas[areaCount] = (uint16)unpackBitsLE(&data[0x11],bitOffset,10);
					areaCount++;
					bitOffset+=10;
				//	printf("SEARCH::Area List Entry found(%2X)!\n",areas[areaCount-1]);
				}
				break;
			}
			case SEARCH_NATION: //Country - 2 bit
			{
				if (isPresent==0x1)
				{
					unsigned char country = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,2);
					bitOffset+=2;

					printf("SEARCH::Nationality Entry found. (%2X) Sorting: (%s).\n",country,(sortDescending==0x00)?"ascending":"descending");
				}
				break;
			}
			case SEARCH_JOB: //Job - 5 bit
			{
				if (isPresent==0x1)
				{
					unsigned char job = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,5);
					bitOffset+=5;
					jobid = job;
					//printf("SEARCH::Job Entry found. (%2X) Sorting: (%s).\n",job,(sortDescending==0x00)?"ascending":"descending");
				}
				//packetData.sortDescendingByJob=sortDescending;
				//printf("SEARCH::SortByJob: %s.\n",(sortDescending==0x00)?"ascending":"descending");
				break;
			}
			case SEARCH_LEVEL: //Level- 16 bit
			{
				if (isPresent==0x1)
				{
					unsigned char fromLvl = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,8);
					bitOffset+=8;
					unsigned char toLvl = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,8);
					bitOffset+=8;
					minLvl = fromLvl;
					maxLvl = toLvl;
					//printf("SEARCH::Level Entry found. (%d - %d) Sorting: (%s).\n",fromLvl,toLvl,(sortDescending==0x00)?"ascending":"descending");
				}
				//packetData.sortDescendingByLevel=sortDescending;
				//printf("SEARCH::SortByLevel: %s.\n",(sortDescending==0x00)?"ascending":"descending");
				break;
			}
			case SEARCH_RACE: //Race - 4 bit
			{
				if (isPresent==0x1)
				{
					unsigned char race = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,4);
					bitOffset+=4;
					printf("SEARCH::Race Entry found. (%2X) Sorting: (%s).\n",race,(sortDescending==0x00)?"ascending":"descending");
				}
				printf("SEARCH::SortByRace: %s.\n",(sortDescending==0x00)?"ascending":"descending");
				//packetData.sortDescendingByRace=sortDescending;
				break;
			}
			case SEARCH_RANK: //Rank - 2 byte
			{
				if (isPresent==0x1)
				{
					unsigned char fromRank = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,8);
					bitOffset+=8;
					unsigned char toRank = (unsigned char)unpackBitsLE(&data[0x11],bitOffset,8);
					bitOffset+=8;

					printf("SEARCH::Rank Entry found. (%d - %d) Sorting: (%s).\n",fromRank,toRank,(sortDescending==0x00)?"ascending":"descending");
				}
				printf("SEARCH::SortByRank: %s.\n",(sortDescending==0x00)?"ascending":"descending");
				//packetData.sortDescendingByRank=sortDescending;
				break;
			}
			case SEARCH_COMMENT: //4 Byte
			{
				unsigned int comment = (unsigned int)unpackBitsLE(&data[0x11],bitOffset,32); 
				bitOffset+=32;

				printf("SEARCH::Comment Entry found. (%8X).\n",comment);
				break;
			}
			//the following 4 Entries were generated with /sea (ballista|friend|linkshell|away|inv) 
			//so they may be off
			case SEARCH_LINKSHELL: // 4 Byte
			{
				unsigned int lsId= (unsigned int)unpackBitsLE(&data[0x11],bitOffset,32);
				bitOffset+=32;

				printf("SEARCH::Linkshell Entry found. Value: %.8X\n",lsId);
				break;
			}
			case SEARCH_FRIEND: // Friend Packet, 0 byte
			{
				printf("SEARCH::Friend Entry found.\n");
				break;
			}
			case SEARCH_FLAGS1: // Flag Entry #1, 2 byte, 
			{ 
				if (isPresent==0x1)
				{
					unsigned short flags1 = (unsigned short)unpackBitsLE(&data[0x11],bitOffset,16);
					bitOffset+=16;

					printf("SEARCH::Flag Entry #1 (%.4X) found. Sorting: (%s).\n",flags1,(sortDescending==0x00)?"ascending":"descending");
				}
				printf("SEARCH::SortByFlags: %s\n",(sortDescending == 0? "ascending" : "descending"));
				//packetData.sortDescendingByFlags=sortDescending;
				break;
			}
			case SEARCH_FLAGS2: // Flag Entry #2 - 4 byte
			{
				unsigned int flags=(unsigned int)unpackBitsLE(&data[0x11],bitOffset,32);

				bitOffset+=32;
				/*
				if ((flags & 0xFFFF)!=(packetData.flags1))
				{
					printf("SEARCH::Flag mismatch: %.8X != %.8X\n",flags,packetData.flags1&0xFFFF);
				}
				packetData.flags2=flags;
				printf("SEARCH::Flag Entry #2 (%.8X) found.\n",packetData.flags2);
				*/
				break;
			}
			default:
			{
				printf("SEARCH::Unknown Search Param %.2X!\n",EntryType);
				//outputPacket=true;
				break;
			}
		}
	}
	printf("\n");

	ShowMessage("Name: %s Job: %u Lvls: %u ~ %u \n",(nameLen>0 ? name : 0),jobid,minLvl,maxLvl);

	search_req sr;
	sr.jobid = jobid;
	sr.maxlvl = maxLvl;
	sr.minlvl = minLvl;
	sr.nameLen = nameLen;
	memcpy(sr.zoneid, areas, sizeof(sr.zoneid));
	if(nameLen>0){
		sr.name.insert(0,(int8*)name);
	}

	return sr;
	// не обрабатываем последние биты, что мешает в одну кучу например "/blacklist delete Name" и "/sea all Name"
}
Beispiel #10
0
uint8 CItemFurnishing::getCol()
{
    return RBUFB(m_extra, 0x06);
}
Beispiel #11
0
uint8 CItemFurnishing::getRotation()
{
    return RBUFB(m_extra, 0x09);
}
Beispiel #12
0
uint8 CItemFurnishing::getLevel()
{
    return RBUFB(m_extra, 0x07);
}
Beispiel #13
0
uint8 CItemFurnishing::getRow()
{
    return RBUFB(m_extra, 0x08);
}
Beispiel #14
0
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;
}
Beispiel #15
0
void CZoneEntities::PushPacket(CBaseEntity* PEntity, GLOBAL_MESSAGE_TYPE message_type, CBasicPacket* packet)
{
	// Do not send packets that are updates of a hidden GM..
	if (packet != NULL && packet->getType() == 0x0D && PEntity != NULL && PEntity->objtype == TYPE_PC && ((CCharEntity*)PEntity)->m_isGMHidden)
	{
		// Ensure this packet is not despawning us..
		if (packet->getData()[0x06] != 0x20)
		{
			delete packet;
			return;
		}
	}

	if (!m_charList.empty())
	{
		switch (message_type)
		{
			case CHAR_INRANGE_SELF:
			{
				if (PEntity->objtype == TYPE_PC)
				{
					((CCharEntity*)PEntity)->pushPacket(new CBasicPacket(*packet));
				}
			}
			case CHAR_INRANGE:
			{
				for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
				{
					CCharEntity* PCurrentChar = (CCharEntity*)it->second;
					if (PEntity != PCurrentChar)
					{
						if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 50)
						{
							if (packet != NULL && packet->getType() == 0x0E &&
								(RBUFB(packet->getData(), (0x0A) - 4) != 0x20 ||
								RBUFB(packet->getData(), (0x0A) - 4) != 0x0F))
							{
								uint32 id = RBUFL(packet->getData(), (0x04) - 4);
								uint16 targid = RBUFW(packet->getData(), (0x08) - 4);

								CBaseEntity* entity = GetEntity(targid);

								SpawnIDList_t spawnlist;

								if (entity)
								{
									if (entity->targid < 0x400)
									{
										if (entity->objtype == TYPE_MOB)
										{
											spawnlist = PCurrentChar->SpawnMOBList;
										}
										else if (entity->objtype == TYPE_NPC)
										{
											spawnlist = PCurrentChar->SpawnNPCList;
										}
									}
									else if (entity->targid >= 0x700)
									{
										spawnlist = PCurrentChar->SpawnPETList;
									}
									else
									{
										entity = NULL;
									}
								}
								if (!entity)
								{
									// got a char or nothing as the target of this entity update (which really shouldn't happen ever)
									// so we're just going to skip this packet
									break;
								}
								SpawnIDList_t::iterator iter = spawnlist.lower_bound(id);

								if (!(iter == spawnlist.end() ||
									spawnlist.key_comp()(id, iter->first)))
								{
									PCurrentChar->pushPacket(new CBasicPacket(*packet));
								}
							}
							else
							{
								PCurrentChar->pushPacket(new CBasicPacket(*packet));
							}
						}
					}
				}
			}
			break;
			case CHAR_INSHOUT:
			{
				for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
				{
					CCharEntity* PCurrentChar = (CCharEntity*)it->second;
					if (PEntity != PCurrentChar)
					{
						if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 180)
						{
							PCurrentChar->pushPacket(new CBasicPacket(*packet));
						}
					}
				}
			}
			break;
			case CHAR_INZONE:
			{
				for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
				{
					CCharEntity* PCurrentChar = (CCharEntity*)it->second;
					if (PEntity != PCurrentChar)
					{
						PCurrentChar->pushPacket(new CBasicPacket(*packet));
					}
				}
			}
			break;
		}
	}
	delete packet;
}