DTerr DeviceNetworkSockets::tcp_recv (NetworkPacket &packet, const NetworkSocket &socket) { if (socket.is_empty()) return DT3_ERR_NONE; DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data()); ssize_t size = ::recv( socket_raw, packet.data(), (DTuint) packet.data_size(), 0 ); if (size < 0) { packet.set_data_size(0); switch (errno) { //case EAGAIN: // Same as EWOULDBLOCK case EWOULDBLOCK: return DT3_ERR_NET_WOULD_BLOCK; default: LOG_MESSAGE << "TCPRecv: recv: " << strerror(errno) << " (" << (DTuint) errno << ")"; return DT3_ERR_NET_UNKNOWN; }; } else { packet.set_data_size(size); } return DT3_ERR_NONE; }
DTerr DeviceNetworkSockets::udp_recv (NetworkPacket &packet, const NetworkSocket &socket) { if (socket.is_empty()) return DT3_ERR_NONE; DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data()); struct sockaddr from; socklen_t from_size = sizeof(from); DTsize size = ::recvfrom( socket_raw, packet.data(), (DTuint) packet.data_size(), 0, &from, &from_size ); if (size > 0) { packet.set_network_address( address_to_string(&from) ); packet.set_data_size(size); } else { switch (errno) { case EWOULDBLOCK: return DT3_ERR_NET_WOULD_BLOCK; default: return DT3_ERR_NET_UNKNOWN; }; } return DT3_ERR_NONE; }
DTerr DeviceNetworkSockets::udp_send (const NetworkPacket &packet, const NetworkSocket &socket) { if (socket.is_empty()) return DT3_ERR_NONE; DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data()); struct sockaddr_storage sast = string_to_address(packet.network_address().network_address()); struct sockaddr *sa = (struct sockaddr *) &sast; #if DT3_OS == DT3_ANDROID ::sendto( socket_raw, packet.data(), packet.data_size(), 0, sa, sizeof(sockaddr)); #else ::sendto( socket_raw, packet.data(), (DTuint) packet.data_size(), 0, sa, sa->sa_len); #endif return DT3_ERR_NONE; }
void Controller::shutDown(void) { NetworkPacket *grid = editor->writeToSerialization(); setDataForUserInterfaceKey("environment", grid->getNetworkLength(), (void *) grid); free(grid); }
void Network::SendServerPacket(NetworkPacket packet, const bool reliable) { if(_isConnected && _isServer) { ENetPacket* enetPacket = enet_packet_create(packet.GetBytes(), packet.GetSize(), reliable); enet_host_broadcast(_host, 0, enetPacket); } }
s32 NetworkBaseUDP::sendPacketToAddress( SOCKET Socket, const NetworkPacket &Packet, const sockaddr_in &Address) { /* Send network packet to raw address */ return sendto( Socket, Packet.getRealBuffer(), Packet.getRealBufferSize(), 0, (sockaddr*)&Address, sizeof(sockaddr_in) ); }
void MuxDemux :: remote_input_notify(Ticks_t when, void* data, int port) { NetworkPacket* pkt = (NetworkPacket*)data; if(pkt->get_type() == CREDIT_MSG_TYPE) { //ignore } else { if(m_input_msg_ticks.size() > 0) { assert(m_input_msg_ticks.back() <= when); } m_input_msg_ticks.push_back(when); } }
void Network::SendPacket(NetworkPacket packet, const bool reliable) { if(_isConnected) { ENetPacket* enetPacket = enet_packet_create(packet.GetBytes(), packet.GetSize(), reliable); if(!_isServer) enet_peer_send(_peer, 0, enetPacket); else { _mutex.lock(); _receivedPackets.push_back(NetworkPacket(enetPacket,0)); _mutex.unlock(); } } }
DTerr DeviceNetworkSockets::tcp_send (const NetworkPacket &packet, const NetworkSocket &socket) { if (socket.is_empty()) return DT3_ERR_NONE; DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data()); ::send( socket_raw, packet.data(), (DTuint) packet.data_size(), 0 ); return DT3_ERR_NONE; }
void UdpMulticastChannel::notify_received(char* data, size_t sz,boost::asio::ip::udp::endpoint sender_endpoint) { std::vector<unsigned>* lost; NetworkPacket* packet = new NetworkPacket; if (packet->ParseFromArray(data,sz)) { lost = incoming->add_packet(packet); if (lost->size() > 0 ) { send_nack(packet,sender_endpoint,lost); } } //std::cout << "Received: " << sz << " bytes " << std::endl; receive_from_network(); }
bool ReceivedPacketProcessor::process() { if (_packets.size() == 0) { _waitingOnPacketsMutex.lock(); _hasPackets.wait(&_waitingOnPacketsMutex); _waitingOnPacketsMutex.unlock(); } while (_packets.size() > 0) { lock(); // lock to make sure nothing changes on us NetworkPacket& packet = _packets.front(); // get the oldest packet NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us _packets.erase(_packets.begin()); // remove the oldest packet _nodePacketCounts[temporary.getNode()->getUUID()]--; unlock(); // let others add to the packets processPacket(temporary.getNode(), temporary.getByteArray()); // process our temporary copy } return isStillRunning(); // keep running till they terminate us }
bool ReceivedPacketProcessor::process() { // If a derived class handles process sleeping, like the JurisdiciontListener, then it can set // this _dontSleep member and we will honor that request. if (_packets.size() == 0 && !_dontSleep) { const uint64_t RECEIVED_THREAD_SLEEP_INTERVAL = (1000 * 1000)/60; // check at 60fps usleep(RECEIVED_THREAD_SLEEP_INTERVAL); } while (_packets.size() > 0) { lock(); // lock to make sure nothing changes on us NetworkPacket& packet = _packets.front(); // get the oldest packet NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us _packets.erase(_packets.begin()); // remove the oldest packet unlock(); // let others add to the packets processPacket(temporary.getAddress(), temporary.getData(), temporary.getLength()); // process our temporary copy } return isStillRunning(); // keep running till they terminate us }
void UdpMulticastChannel::read_from_network() { boost::asio::ip::udp::endpoint sender_endpoint; unsigned int sz = MAX_PACKET_SIZE; std::vector<unsigned>* lost; char* data = new char[sz]; receiver->sync_receive(data,sz,&sender_endpoint); NetworkPacket* packet = new NetworkPacket; if (packet->ParseFromArray(data,sz)) { lost = incoming->add_packet(packet); if (lost->size() > 0 ) { //send message to endpoint to resent data //sender->sync_send() } } delete data; }
void Network::DistributePacket(NetworkPacket networkPacket) { int type = networkPacket.GetType(); if (type >= 0 && type < LAST_TYPE) { std::list<INetworkListener*>::const_iterator iterator; for (iterator = _listeners[type]->begin(); iterator != _listeners[type]->end(); ++iterator) (*iterator)->HandleNetworkMessage(networkPacket); } else printf("Unknown PacketType '%s' received", type); }
// We may be called more frequently than we get packets or need to send packets, we may also get called less frequently. // // If we're called more often then out target PPS then we will space out our actual sends to be a single packet for multiple // calls to process. Those calls to proces in which we do not need to send a packet to keep up with our target PPS we will // just track our call rate (in order to predict our sends per call) but we won't actually send any packets. // // When we are called less frequently than we have packets to send, we will send enough packets per call to keep up with our // target PPS. // // We also keep a running total of packets sent over multiple calls to process() so that we can adjust up or down for // possible rounding error that would occur if we only considered whole integer packet counts per call to process bool PacketSender::nonThreadedProcess() { quint64 now = usecTimestampNow(); if (_lastProcessCallTime == 0) { _lastProcessCallTime = now - _usecsPerProcessCallHint; } const quint64 MINIMUM_POSSIBLE_CALL_TIME = 10; // in usecs const quint64 USECS_PER_SECOND = 1000 * 1000; const float ZERO_RESET_CALLS_PER_SECOND = 1; // used in guard against divide by zero // keep track of our process call times, so we have a reliable account of how often our caller calls us quint64 elapsedSinceLastCall = now - _lastProcessCallTime; _lastProcessCallTime = now; _averageProcessCallTime.updateAverage(elapsedSinceLastCall); float averageCallTime = 0; const int TRUST_AVERAGE_AFTER = AVERAGE_CALL_TIME_SAMPLES * 2; if (_usecsPerProcessCallHint == 0 || _averageProcessCallTime.getSampleCount() > TRUST_AVERAGE_AFTER) { averageCallTime = _averageProcessCallTime.getAverage(); } else { averageCallTime = _usecsPerProcessCallHint; } if (_packets.size() == 0) { // in non-threaded mode, if there's nothing to do, just return, keep running till they terminate us return isStillRunning(); } // This only happens once, the first time we get this far... so we can use it as an accurate initialization // point for these important timing variables if (_lastPPSCheck == 0) { _lastPPSCheck = now; // pretend like our lifetime began once call cycle for now, this makes our lifetime PPS start out most accurately _started = now - (quint64)averageCallTime; } float averagePacketsPerCall = 0; // might be less than 1, if our caller calls us more frequently than the target PPS int packetsSentThisCall = 0; int packetsToSendThisCall = 0; // Since we're in non-threaded mode, we need to determine how many packets to send per call to process // based on how often we get called... We do this by keeping a running average of our call times, and we determine // how many packets to send per call // We assume you can't possibly call us less than MINIMUM_POSSIBLE_CALL_TIME apart if (averageCallTime <= 0) { averageCallTime = MINIMUM_POSSIBLE_CALL_TIME; } // we can determine how many packets we need to send per call to achieve our desired // packets per second send rate. float callsPerSecond = USECS_PER_SECOND / averageCallTime; // theoretically we could get called less than 1 time per second... but since we're using floats, it really shouldn't be // possible to get 0 calls per second, but we will guard agains that here, just in case. if (callsPerSecond == 0) { callsPerSecond = ZERO_RESET_CALLS_PER_SECOND; } // This is the average number of packets per call... averagePacketsPerCall = _packetsPerSecond / callsPerSecond; packetsToSendThisCall = averagePacketsPerCall; // if we get called more than 1 per second, we want to mostly divide the packets evenly across the calls... // but we want to track the remainder and make sure over the course of a second, we are sending the target PPS // e.g. // 200pps called 60 times per second... // 200/60 = 3.333... so really... // each call we should send 3 // every 3rd call we should send 4... // 3,3,4,3,3,4...3,3,4 = 200... // if we get called less than 1 per second, then we want to send more than our PPS each time... // e.g. // 200pps called ever 1332.5ms // 200 / (1000/1332.5) = 200/(0.7505) = 266.5 packets per call // so... // every other call we should send 266 packets // then on the next call we should send 267 packets // So no mater whether or not we're getting called more or less than once per second, we still need to do some bookkeeping // to make sure we send a few extra packets to even out our flow rate. quint64 elapsedSinceLastCheck = now - _lastPPSCheck; // we might want to tun this in the future and only check after a certain number of call intervals. for now we check // each time and adjust accordingly const float CALL_INTERVALS_TO_CHECK = 1; const float MIN_CALL_INTERVALS_PER_RESET = 5; // we will reset our check PPS and time each second (callsPerSecond) or at least 5 calls (if we get called less frequently // than 5 times per second) This gives us sufficient smoothing in our packet adjustments float callIntervalsPerReset = std::max(callsPerSecond, MIN_CALL_INTERVALS_PER_RESET); if (elapsedSinceLastCheck > (averageCallTime * CALL_INTERVALS_TO_CHECK)) { float ppsOverCheckInterval = (float)_packetsOverCheckInterval; float ppsExpectedForCheckInterval = (float)_packetsPerSecond * ((float)elapsedSinceLastCheck / (float)USECS_PER_SECOND); if (ppsOverCheckInterval < ppsExpectedForCheckInterval) { int adjust = ppsExpectedForCheckInterval - ppsOverCheckInterval; packetsToSendThisCall += adjust; } else if (ppsOverCheckInterval > ppsExpectedForCheckInterval) { int adjust = ppsOverCheckInterval - ppsExpectedForCheckInterval; packetsToSendThisCall -= adjust; } // now, do we want to reset the check interval? don't want to completely reset, because we would still have // a rounding error. instead, we check to see that we've passed the reset interval (which is much larger than // the check interval), and on those reset intervals we take the second half average and keep that for the next // interval window... if (elapsedSinceLastCheck > (averageCallTime * callIntervalsPerReset)) { // Keep average packets and time for "second half" of check interval _lastPPSCheck += (elapsedSinceLastCheck / 2); _packetsOverCheckInterval = (_packetsOverCheckInterval / 2); elapsedSinceLastCheck = now - _lastPPSCheck; } } int packetsLeft = _packets.size(); // Now that we know how many packets to send this call to process, just send them. while ((packetsSentThisCall < packetsToSendThisCall) && (packetsLeft > 0)) { lock(); NetworkPacket& packet = _packets.front(); NetworkPacket temporary = packet; // make a copy _packets.erase(_packets.begin()); packetsLeft = _packets.size(); unlock(); // send the packet through the NodeList... NodeList::getInstance()->writeDatagram(temporary.getByteArray(), temporary.getDestinationNode()); packetsSentThisCall++; _packetsOverCheckInterval++; _totalPacketsSent++; _totalBytesSent += temporary.getByteArray().size(); emit packetSent(temporary.getByteArray().size()); _lastSendTime = now; } return isStillRunning(); }
void QueryHandler::HandleMsg( NetworkPacket & recv_data, GameClient *pClient ) { NetworkPacket data; char f[256]; sprintf(f, "WORLD: Query Opcode 0x%.4X", recv_data.opcode); LOG.outString( f ); switch (recv_data.opcode) { case CMSG_NAME_QUERY: { uint32 guid; memcpy(&guid, recv_data.data, 4); uint32 race = 0, gender = 0, cl = 0; char name[32]; std::map<uint32, Character*>::iterator itr = WORLDSERVER.mCharacters.find(guid); if (itr == WORLDSERVER.mCharacters.end()) { DatabaseInterface *dbi = DATABASE.createDatabaseInterface( ); if (!dbi->GetPlayerNameFromGUID(1, (uint8*)name)) LOG.outString( "No player name found for this guid" ); DATABASE.removeDatabaseInterface( dbi ); } else { Character *pChar = WORLDSERVER.mCharacters[guid]; race = pChar->getRace(); gender = pChar->getGender(); cl = pChar->getClass(); strcpy(name, pChar->getName()); } data.Clear(); data.length = 8 + strlen(name)+ 1 + 4*sizeof(uint32); data.data = new uint8[ data.length ]; data.opcode = SMSG_NAME_QUERY_RESPONSE; LOG.outString( name ); data << guid << uint32(0); data << (std::string)name << uint32(0); data << race << gender << cl; // FIXME, something wrong here, crashes client. pClient->SendMsg( &data ); } break; case CMSG_QUERY_TIME: { data.Clear(); data.Initialize(4, SMSG_QUERY_TIME_RESPONSE); data << (int32)time(NULL); pClient->SendMsg(&data); }break; case CMSG_CREATURE_QUERY: { uint32 entry=0; uint32 guid=0; recv_data.ReadData(entry); recv_data.ReadData(guid); uint8 *name = 0; /*std::map<uint32, uint8*>::iterator itr = WORLDSERVER.mCreatureNames.find(entry); if (itr == WORLDSERVER.mCreatureNames.end()){ WPAssert(!"invalid creature entry"); }*/ name = WORLDSERVER.mCreatureNames[entry]; if (!name) name = (uint8 *)"ERROR_NO_CREATURENAME_FOR_ENTRY"; // return; printf(" WORLD: CMSG_CREATURE_QUERY '%s'\n", name ); uint16 namesize = strlen((char*)name)+1; data.Clear(); data.Initialize(4+namesize+16, SMSG_CREATURE_QUERY_RESPONSE); data << (uint32)entry; strcpy((char*)data.data+4, (char*)name); uint8 somedata[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; memcpy(data.data+namesize+4, somedata, 16); pClient->SendMsg(&data); }break; case CMSG_GAMEOBJECT_QUERY: { data.Initialize( 64, SMSG_GAMEOBJECT_QUERY_RESPONSE ); //TODO: Check the database for the ENTRY (First long) and obtain all the details from there... data << uint32( 0x00000787 ) << uint32( 0x00000013 ) << uint32( 0x0000088e ); data << uint32( 0x6c69614d ) << uint32( 0x00786f62 ); data << uint32( 0x00000000 ) << uint32( 0x00000000 ) << uint32( 0x00000000 ); data << uint32( 0x00000000 ); data << uint32( 0 ) << uint32( 0 ) << uint32( 0 ) << uint32( 0 ) << uint32( 0 ) << uint32( 0 ); data << uint16( 0 ) << uint8( 0 ); /* 00 00 07 87 00 00 00 08 00 00 00 C0 54 F9 EC 01 04 00 00 00 0A 00 00 00 12 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4F 52 44 45 52 */ /* Mailbox 22 33 02 00 // ENTRY 13 00 00 00 // Unknown 8e 08 00 00 // Display_id 4d 61 69 6c | 62 6f 78 00 // Mailbox (Null terminated) 00 00 00 00 // 1 00 00 00 00 // 2 00 00 00 00 // 3 00 00 00 00 // 4 00 00 00 00 // 5 00 00 00 00 // 6 00 00 00 00 // 7 00 00 00 00 // 8 00 00 00 00 // 9 00 00 00 00 // 10 00 00 00 // 11 */ pClient->SendMsg( &data ); LOG.outString( "WORLD: Sent Object Query Response." ); }break; } }
void TestConnection::testConnectSendReceive() { DSTACK("TestConnection::Run"); /* Test some real connections NOTE: This mostly tests the legacy interface. */ u32 proto_id = 0xad26846a; Handler hand_server("server"); Handler hand_client("client"); Address address(0, 0, 0, 0, 30001); Address bind_addr(0, 0, 0, 0, 30001); /* * Try to use the bind_address for servers with no localhost address * For example: FreeBSD jails */ std::string bind_str = g_settings->get("bind_address"); try { bind_addr.Resolve(bind_str.c_str()); if (!bind_addr.isIPv6()) { address = bind_addr; } } catch (ResolveError &e) { } infostream << "** Creating server Connection" << std::endl; con::Connection server(proto_id, 512, 5.0, false, &hand_server); server.Serve(address); infostream << "** Creating client Connection" << std::endl; con::Connection client(proto_id, 512, 5.0, false, &hand_client); UASSERT(hand_server.count == 0); UASSERT(hand_client.count == 0); sleep_ms(50); Address server_address(127, 0, 0, 1, 30001); if (address != Address(0, 0, 0, 0, 30001)) { server_address = bind_addr; } infostream << "** running client.Connect()" << std::endl; client.Connect(server_address); sleep_ms(50); // Client should not have added client yet UASSERT(hand_client.count == 0); try { NetworkPacket pkt; infostream << "** running client.Receive()" << std::endl; client.Receive(&pkt); infostream << "** Client received: peer_id=" << pkt.getPeerId() << ", size=" << pkt.getSize() << std::endl; } catch (con::NoIncomingDataException &e) { } // Client should have added server now UASSERT(hand_client.count == 1); UASSERT(hand_client.last_id == 1); // Server should not have added client yet UASSERT(hand_server.count == 0); sleep_ms(100); try { NetworkPacket pkt; infostream << "** running server.Receive()" << std::endl; server.Receive(&pkt); infostream << "** Server received: peer_id=" << pkt.getPeerId() << ", size=" << pkt.getSize() << std::endl; } catch (con::NoIncomingDataException &e) { // No actual data received, but the client has // probably been connected } // Client should be the same UASSERT(hand_client.count == 1); UASSERT(hand_client.last_id == 1); // Server should have the client UASSERT(hand_server.count == 1); UASSERT(hand_server.last_id == 2); //sleep_ms(50); while (client.Connected() == false) { try { NetworkPacket pkt; infostream << "** running client.Receive()" << std::endl; client.Receive(&pkt); infostream << "** Client received: peer_id=" << pkt.getPeerId() << ", size=" << pkt.getSize() << std::endl; } catch (con::NoIncomingDataException &e) { } sleep_ms(50); } sleep_ms(50); try { NetworkPacket pkt; infostream << "** running server.Receive()" << std::endl; server.Receive(&pkt); infostream << "** Server received: peer_id=" << pkt.getPeerId() << ", size=" << pkt.getSize() << std::endl; } catch (con::NoIncomingDataException &e) { } /* Simple send-receive test */ { NetworkPacket pkt; pkt.putRawPacket((u8*) "Hello World !", 14, 0); Buffer<u8> sentdata = pkt.oldForgePacket(); infostream<<"** running client.Send()"<<std::endl; client.Send(PEER_ID_SERVER, 0, &pkt, true); sleep_ms(50); NetworkPacket recvpacket; infostream << "** running server.Receive()" << std::endl; server.Receive(&recvpacket); infostream << "** Server received: peer_id=" << pkt.getPeerId() << ", size=" << pkt.getSize() << ", data=" << (const char*)pkt.getU8Ptr(0) << std::endl; Buffer<u8> recvdata = pkt.oldForgePacket(); UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0); } u16 peer_id_client = 2; /* Send a large packet */ { const int datasize = 30000; NetworkPacket pkt(0, datasize); for (u16 i=0; i<datasize; i++) { pkt << (u8) i/4; } infostream << "Sending data (size=" << datasize << "):"; for (int i = 0; i < datasize && i < 20; i++) { if (i % 2 == 0) infostream << " "; char buf[10]; snprintf(buf, 10, "%.2X", ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff); infostream<<buf; } if (datasize > 20) infostream << "..."; infostream << std::endl; Buffer<u8> sentdata = pkt.oldForgePacket(); server.Send(peer_id_client, 0, &pkt, true); //sleep_ms(3000); Buffer<u8> recvdata; infostream << "** running client.Receive()" << std::endl; u16 peer_id = 132; u16 size = 0; bool received = false; u32 timems0 = porting::getTimeMs(); for (;;) { if (porting::getTimeMs() - timems0 > 5000 || received) break; try { NetworkPacket pkt; client.Receive(&pkt); size = pkt.getSize(); peer_id = pkt.getPeerId(); recvdata = pkt.oldForgePacket(); received = true; } catch (con::NoIncomingDataException &e) { } sleep_ms(10); } UASSERT(received); infostream << "** Client received: peer_id=" << peer_id << ", size=" << size << std::endl; infostream << "Received data (size=" << size << "): "; for (int i = 0; i < size && i < 20; i++) { if (i % 2 == 0) infostream << " "; char buf[10]; snprintf(buf, 10, "%.2X", ((int)(recvdata[i])) & 0xff); infostream << buf; } if (size > 20) infostream << "..."; infostream << std::endl; UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0); UASSERT(peer_id == PEER_ID_SERVER); } // Check peer handlers UASSERT(hand_client.count == 1); UASSERT(hand_client.last_id == 1); UASSERT(hand_server.count == 1); UASSERT(hand_server.last_id == 2); }
void GossipHandler::HandleMsg( NetworkPacket & recv_data, GameClient *pClient ) { NetworkPacket data; char f[256]; sprintf(f, "WORLD: Gossip Opcode 0x%.4X", recv_data.opcode); Log::getSingleton( ).outString( f ); switch (recv_data.opcode) { case CMSG_GOSSIP_HELLO: { uint16 tSize,i; uint32 TextID; guid cguid; recv_data >> cguid.sno >> cguid.type; TextID = getTextID(cguid.sno); if(TextID == 0) { //text Id 0 don't exist so maybe they don't want to talk :P data.Initialize( 8 , SMSG_NPC_WONT_TALK ); data << cguid.sno << cguid.type; pClient->SendMsg (&data); break; } //TextRelation * pRelation = getTextRelation(cguid.sno); NPCText * theText = getNPCText(TextID); //Calculate the size tSize = 20 + (8*theText->m_OptionCount); TextOption * theOption; for(i = 1; i <= theText->m_OptionCount;i++) { // add option textsize to the size theOption = getTextOption(theText->m_OptionID[i]); tSize += strlen((char *)theOption->m_OptionText.c_str())+1; } //Create the Packet data.Initialize( tSize, SMSG_GOSSIP_MESSAGE ); data << cguid.sno << cguid.type; data << (uint32)TextID; //TextID data << (uint32)theText->m_OptionCount; // Bullet Points Count for(i = 1; i <= theText->m_OptionCount;i++) { theOption = getTextOption(theText->m_OptionID[i]); data << (uint32)theOption->m_OptionID; //Bullet Point Number data << (uint32)theOption->m_OptionIconID; //Bullet Point IconID //option text data.WriteData(theOption->m_OptionText.c_str() , strlen((char *)theOption->m_OptionText.c_str())+1 ); } data << (uint32)0; pClient->SendMsg (&data); //pClient->getCurrentChar()->setUpdateValue(CORPSE_FIELD_ITEM3, 6947); //pClient->getCurrentChar()->setUpdateValue(CORPSE_FIELD_ITEM4, (uint32)0xf0001000 ); //pClient->getCurrentChar()->UpdateObject(); }break; case CMSG_GOSSIP_SELECT_OPTION: { uint32 option; guid cguid; recv_data >> cguid.sno >> cguid.type; recv_data >> option; TextOption * theOption; theOption = getTextOption(option); // Textid of 0 is Reserved for exiting and SH Comfirm if(theOption->m_TextID == 0) { Unit *pSelection = world.GetValidCreature(cguid.sno); if(pSelection != 0) { //if the selection is a spirit healer if(pSelection->getUpdateValue(UNIT_NPC_FLAGS) == 32) { // Sh Accept Dialog data.Initialize(8,SMSG_SPIRIT_HEALER_CONFIRM); data << cguid.sno << cguid.type; pClient->SendMsg( &data ); } } //close the Gossip Window data.Initialize(0,SMSG_GOSSIP_COMPLETE); pClient->SendMsg( &data ); break; } uint16 TextID,tSize,i; //get the Text ID TextID = theOption->m_TextID; //get the Related text info NPCText * theText = getNPCText(TextID); //calculate our size tSize = 20 + (8*theText->m_OptionCount); for(i = 1; i <= theText->m_OptionCount;i++) { //get each options text and add it to the size theOption = getTextOption(theText->m_OptionID[i]); tSize += strlen((char *)theOption->m_OptionText.c_str())+1; } //Create the Packet data.Initialize( tSize, SMSG_GOSSIP_MESSAGE ); data << cguid.sno << cguid.type; data << (uint32)TextID; //TextID data << (uint32)theText->m_OptionCount; // Bullet Points Count //Get each option for(i = 1; i <= theText->m_OptionCount;i++) { theOption = getTextOption(theText->m_OptionID[i]); data << (uint32)theOption->m_OptionID; //Bullet Point Number data << (uint32)theOption->m_OptionIconID; //Bullet Point IconID //option text data.WriteData(theOption->m_OptionText.c_str() , strlen((char *)theOption->m_OptionText.c_str())+1 ); } data << (uint32)0; //Null Terminator pClient->SendMsg (&data); }break; case CMSG_NPC_TEXT_QUERY: { uint32 textID, tSize; recv_data >> textID; /* i don't think this is used but if Spirit healers don't work try it :P //this is having to do with spirit healers uint32 uField0, uField1; recv_data >> uField0 >> uField1; Unit pSelection = world.GetValidCreature(uField0); if(pSelection != 0) { if(pSelection.getUpdateValue(UNIT_NPC_FLAGS) == 32) //if the selection is a spirit healer { pClient->getCurrentChar()->setUpdateValue(UNIT_FIELD_TARGET, uField0); pClient->getCurrentChar()->setUpdateValue(UNIT_FIELD_TARGET + 1, uField1); } } */ //get the text from the text id NPCText * theText = getNPCText(textID); //calculate hte size tSize = strlen((char *)theText->m_Text.c_str())+9; //create the packet data.Initialize(tSize, SMSG_NPC_TEXT_UPDATE); data << textID << (uint32)0x42c80000; //text id and text display fix ?? data.WriteData((char *)theText->m_Text.c_str(), strlen((char *)theText->m_Text.c_str())+1); pClient->SendMsg( &data ); }break; default: break; } }
void ItemHandler::HandleMsg (NetworkPacket & recv_data, GameClient *pClient) { NetworkPacket data; char f[ 256 ]; sprintf (f, "WORLDSERVER: Item Opcode 0x%.4X", recv_data.opcode); LOG.outString (f); switch (recv_data.opcode) { case CMSG_SWAP_INV_ITEM: { //ok i'm gonna do that a looootttt cleaner :/ uint8 srcslot, destslot; recv_data >> srcslot >> destslot; int slot = destslot; //START OF LINA LVL REQUIREMENT SWAP PATCH int8 CharLvl, ItemLvl; //printf("ITEM: LVL TEST\n"); CharLvl=pClient->getCurrentChar()->getLevel(); ItemLvl=WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(srcslot))->RequiredLevel; //printf("ITEM: CharLvl %d, ItemLvl %d\n", CharLvl, ItemLvl); if (CharLvl < ItemLvl) { ChatHandler * MsgLvlItem = new ChatHandler; if(MsgLvlItem !=NULL) { //NEED TO PUT SOME CODE TO UNGRAY ITEM uint8 buf[256]; NetworkPacket data; sprintf((char*)buf,"You need the Lvl %d to equip that item.", ItemLvl); MsgLvlItem->FillMessageData(&data, 0x09, pClient, buf); pClient->SendMsg (&data); delete(MsgLvlItem); } else printf("ITEM: CMSG_SWAP_INV_ITEM can't send message\n"); return; } //END OF LINA LVL REQUIREMENT SWAP PATCH //these are the bags slots...ignore it for now if ((slot <= 22) && (slot >=19)) destslot = srcslot; //check to make sure items are not being put in wrong spots if (((srcslot > 23) && (destslot < 19)) || ((srcslot < 23) && (destslot > 19))) { if ((pClient->getCurrentChar()->getGuidBySlot(destslot) != 0) && (pClient->getCurrentChar()->getGuidBySlot(srcslot) != 0)) { Item * tmpitem1 = WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot)); Item * tmpitem2 = WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(srcslot)); if ((tmpitem1 != NULL) && (tmpitem2 != NULL)) { if (tmpitem1->Inventorytype != tmpitem2->Inventorytype) { data.Initialize (18, SMSG_INVENTORY_CHANGE_FAILURE); data << uint8(0x0c) ; data << uint32(pClient->getCurrentChar()->getGuidBySlot(destslot)); data << uint32(0x00000040); data << uint32(pClient->getCurrentChar()->getGuidBySlot(srcslot)); data << uint32(0x00000040); data << uint8(0); pClient->SendMsg (&data); return; } } } } //swap items pClient->getCurrentChar()->SwapItemInSlot((int)srcslot, (int)destslot); UpdateMask updateMask; updateMask.SetLength (PLAYER_FIELDS); //error if (srcslot == destslot) { data.Initialize (18, SMSG_INVENTORY_CHANGE_FAILURE); data << uint8(0x0c) ; data << uint32(pClient->getCurrentChar()->getGuidBySlot(destslot)); data << uint32(0x00000040); data << uint32(pClient->getCurrentChar()->getGuidBySlot(srcslot)); data << uint32(0x00000040); data << uint8(0); pClient->SendMsg (&data); return; } pClient->getCurrentChar()->updateItemStats(); //send to zone players...they don't need to know about the item if the slot is over 19 if (destslot < 19) { pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2), pClient->getCurrentChar()->getGuidBySlot(destslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(destslot) == 0 ? 0 : 0x00000040, updateMask.data); } if (srcslot < 19) { pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2), pClient->getCurrentChar()->getGuidBySlot(srcslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(srcslot) == 0 ? 0 : 0x00000040, updateMask.data); } pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); // WORLDSERVERSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); //send update to the player pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2), pClient->getCurrentChar()->getGuidBySlot(destslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(destslot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2), pClient->getCurrentChar()->getGuidBySlot(srcslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(srcslot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); pClient->SendMsg (&data); if ((srcslot < 19) && (destslot < 19)) return; int invcount = srcslot; if ((pClient->getCurrentChar()->getGuidBySlot(invcount) != 0) && (srcslot < 19)) { createItemUpdate(&data, pClient, invcount); // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); } invcount = destslot; if ((pClient->getCurrentChar()->getGuidBySlot(invcount) != 0) && (destslot < 19)) { createItemUpdate(&data, pClient, invcount); // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); } break; } case CMSG_DESTROYITEM: { uint8 srcslot, destslot; uint32 itemguid; recv_data >> srcslot >> destslot; if (WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot)) != NULL) srcslot = WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot))->Inventorytype && 0xff; else return; if (pClient->getCurrentChar()->getGuidBySlot(destslot) == 0) return; itemguid = pClient->getCurrentChar()->getGuidBySlot(destslot); pClient->getCurrentChar()->AddItemToSlot(destslot,0,0); UpdateMask updateMask; updateMask.SetLength (PLAYER_FIELDS); if (destslot < 19) { pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2), pClient->getCurrentChar()->getGuidBySlot (destslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(destslot) == 0 ? 0 : 0x00000040, updateMask.data); } pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); // WORLDSERVERSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2), pClient->getCurrentChar()->getGuidBySlot(destslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(destslot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); pClient->SendMsg (&data); data.Clear(); data.Initialize(8, SMSG_DESTROY_OBJECT); data << itemguid << uint32(0x00000040); // WORLDSERVER.SendZoneMessage(&data, pClient, 1); pClient->getCurrentChar()->SendMessageToSet(&data, true); break; } case CMSG_AUTOEQUIP_ITEM: { uint8 srcslot, destslot; recv_data >> srcslot >> destslot; int8 CharLvl, ItemLvl; //START OF LINA LVL REQUIREMENT AUTOEQUIP PATCH CharLvl=pClient->getCurrentChar()->getLevel(); ItemLvl=WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot))->RequiredLevel; //printf("ITEM: CharLvl %d, ItemLvl %d\n", CharLvl, ItemLvl); if (CharLvl < ItemLvl) { ChatHandler * MsgLvlItem = new ChatHandler; if (MsgLvlItem != NULL) { //NEED TO PUT SOME CODE TO UNGRAY ITEM uint8 buf[256]; NetworkPacket data; sprintf((char*)buf,"You need the Lvl %d to equip that item.", ItemLvl); MsgLvlItem->FillMessageData(&data, 0x09, pClient, buf); pClient->SendMsg (&data); delete(MsgLvlItem); } else printf("ITEM: CMSG_AUTOEQUIP_ITEM can't send message\n"); return; } //END OF LINA LVL REQUIREMENT AUTOEQUIP PATCH if (WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot)) != NULL) srcslot = uint8(WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot))->Inventorytype); else return; if (WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot))->Class == 4) { if (srcslot < 11) srcslot--; else if (srcslot == 11) { if (pClient->getCurrentChar()->getGuidBySlot(10) == 0) { srcslot = 10; } else if (pClient->getCurrentChar()->getGuidBySlot(11) == 0) { srcslot = 11; } else { srcslot = destslot; } } else if (srcslot == 14) srcslot += 2; else if (srcslot == 13) srcslot += 2; else srcslot = 4; } else if (WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot))->Class == 2) { switch (WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(destslot))->SubClass) { case 2: case 3: case 16: case 19: srcslot = 17; break; default: srcslot = 15; break; } } else { srcslot = destslot; } if (srcslot == destslot) { data.Initialize (18, SMSG_INVENTORY_CHANGE_FAILURE); data << uint8(0x0c) ; data << uint32(pClient->getCurrentChar()->getGuidBySlot(destslot)); data << uint32(0x00000040); data << uint32(0) << uint32(0) << uint8(0); pClient->SendMsg (&data); return; } pClient->getCurrentChar()->SwapItemInSlot((int)srcslot, (int)destslot); UpdateMask updateMask; updateMask.SetLength (PLAYER_FIELDS); if (destslot < 19) { pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2), pClient->getCurrentChar()->getGuidBySlot(destslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(destslot) == 0 ? 0 : 0x00000040, updateMask.data); } if (srcslot < 19) { pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2), pClient->getCurrentChar()->getGuidBySlot(srcslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(srcslot) == 0 ? 0 : 0x00000040, updateMask.data); } pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); // WORLDSERVERSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2), pClient->getCurrentChar()->getGuidBySlot(destslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (destslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(destslot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2), pClient->getCurrentChar()->getGuidBySlot(srcslot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (srcslot*2)+1, pClient->getCurrentChar()->getGuidBySlot(srcslot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); pClient->SendMsg (&data); Item *tempitem; UpdateMask invUpdateMask; int invcount = srcslot; invUpdateMask.SetLength (64); tempitem = new Item; if ((pClient->getCurrentChar()->getGuidBySlot(invcount) != 0) && (srcslot < 19)) { createItemUpdate(&data, pClient, invcount); // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); delete tempitem; } else delete tempitem; invcount = destslot; invUpdateMask.SetLength (64); tempitem = new Item; if (srcslot == destslot) return; if ((pClient->getCurrentChar()->getGuidBySlot(invcount) != 0) && (destslot < 19)) { createItemUpdate(&data, pClient, invcount); // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); } LOG.outString ("WORLDSERVER: Sent Updated Item slot Masks"); break; } case CMSG_ITEM_QUERY_SINGLE: { int i; uint32 itemid, guid1, guid2; recv_data >> itemid >> guid1 >> guid2; // guid is the guid of the ITEM OWNER - NO ITS NOT if (WORLDSERVER.GetItem(itemid) == NULL) return; sprintf (curopcodebuf, "WORLDSERVER: Recvd CMSG_ITEM_QUERY_SINGLE for item id 0x%.8X, guid 0x%.8X 0x%.8X", itemid, guid1, guid2); LOG.outString (curopcodebuf); Item *tempItem = WORLDSERVER.GetItem(itemid); //data.Initialize (413 + tempItem->name1.length() + tempItem->name2.length() + tempItem->name3.length() + tempItem->name4.length() + tempItem->Description.length(), SMSG_ITEM_QUERY_SINGLE_RESPONSE); data.Initialize (413 + 12 + tempItem->name1.length() + tempItem->name2.length() + tempItem->name3.length() + tempItem->name4.length() + tempItem->Description.length(), SMSG_ITEM_QUERY_SINGLE_RESPONSE); //printf("%d\n", data.length); //printf("%s\n%s\n", tempItem->name1.c_str(), tempItem->Description.c_str()); data << itemid; data << tempItem->Class; data << tempItem->SubClass; data << tempItem->name1.c_str(); data << tempItem->name2.c_str(); data << tempItem->name3.c_str(); data << tempItem->name4.c_str(); data << tempItem->DisplayInfoID; data << tempItem->OverallQualityID; data << tempItem->Flags; data << tempItem->Buyprice; data << tempItem->Sellprice; data << tempItem->Inventorytype; data << tempItem->AllowableClass; data << tempItem->AllowableRace; data << tempItem->ItemLevel; data << tempItem->RequiredLevel; data << tempItem->RequiredSkill; data << tempItem->RequiredSkillRank; data << uint32(0); // other requirements here? - 10 = "Requires Blizzard" data << uint32(0); // ??? 10 = "Requires Knight" data << uint32(0); // ??? 10 = "Requires " data << tempItem->MaxCount; data << tempItem->Stackable; data << tempItem->ContainerSlots; for(i = 0; i<10; i++) { data << tempItem->BonusStat[i]; data << tempItem->BonusAmount[i]; } for(i = 0; i<5; i++) { data << (float)(tempItem->MinimumDamage[i]); data << (float)(tempItem->MaximumDamage[i]); data << tempItem->DamageType[i]; } data << tempItem->Resistances[0]; // armor data << uint32(0); // unknown extra resistance data << tempItem->Resistances[2]; // fire data << tempItem->Resistances[3]; // nature data << tempItem->Resistances[4]; // frost data << tempItem->Resistances[5]; // shadow data << tempItem->Resistances[1]; // arcane at the end now //for(i = 0; i<6; i++) //{ // data << tempItem->Resistances[i]; //} data << tempItem->Delay; data << tempItem->AmmunitionType; //data << tempItem->MaxDurability; for(i = 0; i<5; i++) { data << tempItem->SpellID[i]; data << tempItem->SpellTrigger[i]; data << tempItem->SpellCharges[i]; data << tempItem->SpellCooldown[i]; data << tempItem->SpellCategory[i]; data << tempItem->SpellCategoryCooldown[i]; } data << tempItem->Bonding; if (tempItem->Description.c_str()[0] != 48) data << tempItem->Description.c_str(); else data << uint32(0); data << tempItem->Pagetext; data << tempItem->LanguageID; data << tempItem->PageMaterial; data << tempItem->StartQuestID; data << tempItem->LockID; data << tempItem->Material; data << tempItem->Sheathetype; data << tempItem->Unknown1; data << tempItem->Unknown2; pClient->SendMsg (&data); break; } case CMSG_SELL_ITEM: { LOG.outString ("WORLDSERVER: Recieved CMSG_SELL_ITEM"); uint32 srcguid1, srcguid2, itemguid1, itemguid2,newmoney; uint8 amount; recv_data >> srcguid1 >> srcguid2; recv_data >> itemguid1 >> itemguid2; recv_data >> amount; if (itemguid1 == 0) { data.Clear(); data.Initialize(17, SMSG_SELL_ITEM); data << srcguid1 << srcguid2 << itemguid1 << itemguid2 << uint8(0x01); pClient->SendMsg (&data); return; } int itemindex = -1,i,check = 0; Unit *tempunit; tempunit = WORLDSERVER.GetCreature(srcguid1); if (tempunit == NULL) return; for(i = 0; i< 39;i++) { if (pClient->getCurrentChar()->getGuidBySlot(i) == itemguid1) { itemindex = i; break; } } if (itemindex == -1) { data.Clear(); data.Initialize(17, SMSG_SELL_ITEM); data << srcguid1 << srcguid2 << itemguid1 << itemguid2 << uint8(0x01); pClient->SendMsg (&data); return; //our player doesn't have this item } /***************************************************** * i will need to put some stack count check here * *****************************************************/ if (amount == 0) amount = 1; //adding this item to the vendor's item list for(i=0; i<tempunit->getItemCount();i++) { if (tempunit->getItemId(i) == pClient->getCurrentChar()->getItemIdBySlot(itemindex)) { tempunit->setItemAmount(i, tempunit->getItemAmount(i) + amount); check = 1; } } if (check == 0) { if (tempunit->getItemCount() > 100) { data.Clear(); data.Initialize(17, SMSG_SELL_ITEM); data << srcguid1 << srcguid2 << itemguid1 << itemguid2 << uint8(0x02); pClient->SendMsg (&data); return; } else tempunit->addItem(pClient->getCurrentChar()->getItemIdBySlot(itemindex), amount); } newmoney = WORLDSERVER.GetItem(pClient->getCurrentChar()->getItemIdBySlot(itemindex))->Sellprice + pClient->getCurrentChar()->getUpdateValue(PLAYER_FIELD_COINAGE); //removing the item from the char's inventory pClient->getCurrentChar()->AddItemToSlot(itemindex,0,0); //sending a player update UpdateMask updateMask; updateMask.SetLength (PLAYER_FIELDS); if (itemindex < 19) { pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (itemindex*2), pClient->getCurrentChar()->getGuidBySlot(itemindex), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (itemindex*2)+1, pClient->getCurrentChar()->getGuidBySlot(itemindex) == 0 ? 0 : 0x00000040, updateMask.data); } pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); //WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_COINAGE, newmoney, updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (itemindex*2), pClient->getCurrentChar()->getGuidBySlot(itemindex), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (itemindex*2)+1, pClient->getCurrentChar()->getGuidBySlot(itemindex) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); pClient->SendMsg (&data); //send an SMSG_SELL_ITEM data.Clear(); data.Initialize(17, SMSG_SELL_ITEM); data << srcguid1 << srcguid2 << itemguid1 << itemguid2 << uint8(0x05); pClient->SendMsg (&data); //send an object destroy packet data.Clear(); data.Initialize(8, SMSG_DESTROY_OBJECT); data << itemguid1 << uint32(0x00000040); // WORLDSERVER.SendZoneMessage(&data, pClient, 1); pClient->getCurrentChar()->SendMessageToSet(&data, true); break; } case CMSG_BUY_ITEM_IN_SLOT: { LOG.outString ("WORLDSERVER: Recieved CMSG_BUY_ITEM_IN_SLOT"); uint32 srcguid1, srcguid2, itemid, destguid1, destguid2; uint8 slot, amount; recv_data >> srcguid1 >> srcguid2 >> itemid; recv_data >> destguid1 >> destguid2; recv_data >> slot; recv_data >> amount; int itemindex,i,varify = 0; Unit *tempunit; tempunit = WORLDSERVER.GetCreature(srcguid1); if (tempunit == NULL) return; if (slot > 38) return; if (slot < 19) return; if ((slot <= 22) && (slot >=19)) return; //these are the bags slots...i'm not sure exactly how to use them if (pClient->getCurrentChar()->getGuidBySlot(slot) != 0) return; //slot is not empty...i'll have to make code to check for other slots for(i = 0; i< tempunit->getItemCount();i++) { if (tempunit->getItemId(i) == itemid) { varify = 1; break; } } if (varify == 0) return; //our vendor doesn't have this item itemindex = i; if (amount > tempunit->getItemAmount(i)) return; //our vendor doesn't have the required amount of that item tempunit->setItemAmountById(itemid,tempunit->getItemAmount(i) - amount); //START OF LINA BUY PATCH //INFO printf("ARGENT: %d, COUT: %d\n", (pClient->getCurrentChar()->getUpdateValue(PLAYER_FIELD_COINAGE)), (WORLDSERVER.GetItem(tempunit->getItemId(itemindex))->Buyprice)); int32 newmoney; //LINA newmoney = ((pClient->getCurrentChar()->getUpdateValue(PLAYER_FIELD_COINAGE)) - (WORLDSERVER.GetItem(tempunit->getItemId(itemindex))->Buyprice)); printf("DIF: %d\n",newmoney); //INFO if(newmoney < 0) { ChatHandler * MsgGold = new ChatHandler; if (MsgGold != NULL) { uint8 buf[256]; NetworkPacket data; sprintf((char*)buf,"You need %i to buy this item.", abs(newmoney)); MsgGold->FillMessageData(&data, 0x09, pClient, buf); pClient->SendMsg (&data); delete(MsgGold); } else printf("ITEM: CMSG_BUY_ITEM_IN_SLOT can't send message\n"); return; } //END OF LINA BUY PATCH WORLDSERVER.m_hiItemGuid++; std::string templog; char tempiid[10]; sprintf(tempiid,"%d",WORLDSERVER.m_hiItemGuid); templog = "Created Item. Guid: "; templog+= tempiid; LOG.outString (templog.c_str()); pClient->getCurrentChar()->AddItemToSlot(slot,WORLDSERVER.m_hiItemGuid,itemid); data.Clear(); data.Initialize(16, SMSG_BUY_ITEM); data << uint32(srcguid1) << uint32(srcguid2); data << uint32(itemid) << uint32(amount); pClient->SendMsg (&data); Item *tempitem; UpdateMask invUpdateMask; int invcount = slot; invUpdateMask.SetLength (64); tempitem = new Item; createItemUpdate(&data, pClient, invcount); if (slot > 23) pClient->SendMsg (&data); else { // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, true); // pClient->SendMsg (&data); } delete tempitem; UpdateMask updateMask; updateMask.SetLength (PLAYER_FIELDS); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_COINAGE, newmoney, updateMask.data); //LINA BUY PATCH NEXT pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (slot*2), pClient->getCurrentChar()->getGuidBySlot(slot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (slot*2)+1, pClient->getCurrentChar()->getGuidBySlot(slot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); if (slot > 23) pClient->SendMsg (&data); else { // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, true); // pClient->SendMsg (&data); } break; } case CMSG_BUY_ITEM: //right click { LOG.outString ("WORLDSERVER: Recieved CMSG_BUY_ITEM"); uint32 srcguid1, srcguid2, itemid; uint8 slot, amount; recv_data >> srcguid1 >> srcguid2 >> itemid; recv_data >> amount >> slot; int itemindex,i,varify = 0; Unit *tempunit; tempunit = WORLDSERVER.GetCreature(srcguid1); if (tempunit == NULL) return; slot = 0; for(i = 23; i <= 38; i++) { if (pClient->getCurrentChar()->getGuidBySlot(i) == 0) { slot = i; break; } } if (slot == 0) return; for(i = 0; i< tempunit->getItemCount();i++) { if (tempunit->getItemId(i) == itemid) { varify = 1; break; } } if (varify == 0) return; //our vendor doesn't have this item itemindex = i; if (amount > tempunit->getItemAmount(i)) return; //our vendor doesn't have the required amount of that item tempunit->setItemAmountById(itemid,tempunit->getItemAmount(i) - amount); //START OF LINA BUY PATCH //INFO printf("ARGENT: %d, COUT: %d\n", (pClient->getCurrentChar()->getUpdateValue(PLAYER_FIELD_COINAGE)), (WORLDSERVER.GetItem(tempunit->getItemId(itemindex))->Buyprice)); int32 newmoney; //LINA newmoney = ((pClient->getCurrentChar()->getUpdateValue(PLAYER_FIELD_COINAGE)) - (WORLDSERVER.GetItem(tempunit->getItemId(itemindex))->Buyprice)); printf("DIF: %d\n",newmoney); //INFO if(newmoney < 0) { //NEED TO PUT SOME CODE TO UNGRAY ITEM AND SEND A MESSAGE TO PLAYER ChatHandler * MsgGold = new ChatHandler; if (MsgGold != NULL) { uint8 buf[256]; NetworkPacket data; sprintf((char*)buf,"You need %i to buy this item.", abs(newmoney)); MsgGold->FillMessageData(&data, 0x09, pClient, buf); pClient->SendMsg (&data); delete(MsgGold); } else printf("ITEM: CMSG_BUY_ITEM can't send message\n"); return; } //END OF LINA BUY PATCH WORLDSERVER.m_hiItemGuid++; std::string templog; char tempiid[10]; sprintf(tempiid,"%d",WORLDSERVER.m_hiItemGuid); templog = "Created Item. Guid: "; templog+= tempiid; LOG.outString (templog.c_str()); pClient->getCurrentChar()->AddItemToSlot(slot,WORLDSERVER.m_hiItemGuid,itemid); UpdateMask invUpdateMask; int invcount = slot; invUpdateMask.SetLength (64); createItemUpdate(&data, pClient, invcount); if (slot > 23) pClient->SendMsg (&data); else { // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, true); // pClient->SendMsg (&data); } UpdateMask updateMask; updateMask.SetLength (PLAYER_FIELDS); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_COINAGE, newmoney, updateMask.data); //LINA BUY PATCH NEXT pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (slot*2), pClient->getCurrentChar()->getGuidBySlot(slot), updateMask.data); pClient->getCurrentChar ()->setUpdateValue ( PLAYER_FIELD_INV_SLOT_HEAD + (slot*2)+1, pClient->getCurrentChar()->getGuidBySlot(slot) == 0 ? 0 : 0x00000040, updateMask.data); pClient->getCurrentChar ()->UpdateObject (&updateMask, &data); if (slot > 23) pClient->SendMsg (&data); else { // WORLDSERVER.SendZoneMessage(&data, pClient, 0); pClient->getCurrentChar()->SendMessageToSet(&data, false); // pClient->SendMsg (&data); } break; } case CMSG_LIST_INVENTORY: { LOG.outString ("WORLDSERVER: Recvd CMSG_LIST_INVENTORY Message"); uint32 guid1, guid2; //guid1+guid2 = npc's full uint64 guid recv_data >> guid1 >> guid2; Unit *tempunit; tempunit = WORLDSERVER.GetCreature(guid1); if (tempunit == NULL) return; uint8 numitems = (uint8)tempunit->getItemCount(); if (numitems == 0) return; data.Initialize (8 + 1 + numitems * 7 * 4, SMSG_LIST_INVENTORY); data << guid1 << guid2; data << uint8 (numitems); // num items // each item has seven uint32's Item * curItem; for(uint8 itemcount = 0; itemcount < numitems; itemcount ++) { curItem = WORLDSERVER.GetItem(tempunit->getItemId(itemcount)); if (!curItem) { LOG.outError ("Unit %i has nonexistant item %i!", guid1, tempunit->getItemId(itemcount)); LOG.outString ("WORLDSERVER: DID NOT Send SMSG_LIST_INVENTORY Message"); for (int a = 0; a < 7; a ++) data << uint32 (0); } else { data << uint32 (itemcount + 1); // index ? doesn't seem to affect anything // item id data << uint32 (tempunit->getItemId(itemcount)); data << uint32 (curItem->DisplayInfoID);// item icon // number of items available, -1 works for infinity, although maybe just 'cause it's really big data << uint32 (tempunit->getItemAmount(itemcount)); data << uint32 (curItem->Buyprice); // price data << uint32 (0); // ? data << uint32 (0); // ? } } //data.WriteData (tdata, sizeof (tdata)); pClient->SendMsg (&data); LOG.outString ("WORLDSERVER: Sent SMSG_LIST_INVENTORY Message"); break; } } }
void AssetDownloader::downloader_task ( const URL url, const FilePath save_path, DTfloat timeout) { std::shared_ptr<DeviceNetwork> network = System::network_manager(); // // Connecting Phase // // Update status update_status (STATUS_CONNECTING, 0,0); // Resolve the host NetworkSocket socket; NetworkAddress ip; DTerr err = network->resolve_host( ip, url.hostname(), url.port() ); if (err != DT3_ERR_NONE) { LOG_MESSAGE << "HTTPRequest: Unable to resolve host."; update_status (STATUS_ERROR, 0,0); return; } err = network->tcp_open(socket,ip); if (err != DT3_ERR_NONE) { LOG_MESSAGE << "HTTPRequest: Unable to resolve host."; update_status (STATUS_ERROR, 0,0); return; } // Send http request std::string server = url.hostname(); std::string path = url.path(); // Note: // HTTP/1.1 defines the "close" connection option for the sender to signal that the connection // will be closed after completion of the response. For example, // Connection: close // in either the request or the response header fields indicates that the connection SHOULD NOT // be considered `persistent' (section 8.1) after the current request/response is complete. // HTTP/1.1 applications that do not support persistent connections MUST include the "close" // connection option in every message. std::string request = "GET " + path + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "User-Agent: DT3\r\n" + "Accept: */*\r\n" + "Cache-Control: max-age=0\r\n" + "Connection: close\r\n" + "\r\n"; LOG_MESSAGE << "Sending..."; LOG_MESSAGE << request; NetworkPacket packet_request; packet_request.set_data(request); err = network->tcp_send(packet_request, socket); if (err != DT3_ERR_NONE) { network->tcp_close(socket); LOG_MESSAGE << "HTTPRequest: Unable to send packet."; update_status (STATUS_ERROR, 0,0); return; } // // Downloading Phase // update_status (STATUS_DOWNLOADING, 0,0); // Hash the URL FilePath temp_file_path = FilePath(HAL::save_dir().full_path() + "/" + MoreStrings::cast_to_string(MoreStrings::hash(url.full_url()))); // Create a temporary file BinaryFileStream temp_file; err = FileManager::open(temp_file, temp_file_path, false); if (err != DT3_ERR_NONE) { network->tcp_close(socket); LOG_MESSAGE << "HTTPRequest: Unable to open file for writing."; update_status (STATUS_ERROR, 0,0); return; } LOG_MESSAGE << "HTTPRequest: Opened temp file at " << temp_file_path.full_path(); // Temporary storage for buffer std::string data; // Timer for timeout TimerHires timeout_timer; do { // Get the results NetworkPacket packet; packet.set_data_size(1024*16); err = network->tcp_recv(packet,socket); // If we recieved some data, append it to the buffer if (packet.data_size() > 0) { data += packet.data_as_string(); append_data(data, temp_file); timeout_timer.reset_abs_time(); } // Check complete if ( (_current_size == _total_size) && (_total_size > 0) ) { break; } // If we hit our timeout, then we abort if (timeout_timer.abs_time() > timeout) { network->tcp_close(socket); LOG_MESSAGE << "Http request timed out!"; update_status (STATUS_ERROR, 0,0); // Remove the temporary file temp_file_path.del(); return; } // Check for cancel if (_cancelled) { network->tcp_close(socket); LOG_MESSAGE << "Http request cancelled!"; update_status (STATUS_CANCELLED, 0,0); // Remove the temporary file temp_file_path.del(); return; } } while (err == DT3_ERR_NET_WOULD_BLOCK || err == DT3_ERR_NONE); // Close the connection, we're done network->tcp_close(socket); // Close off the stream finalize_data(data, temp_file); // // Finalizing phase // // Move the file save_path.del(); temp_file_path.move(save_path); LOG_MESSAGE << "Saving file to " << save_path.full_path(); // Final update of status update_status (STATUS_COMPLETE, _current_size, _total_size); }
NetworkPacket::NetworkPacket(const NetworkPacket& packet) { copyContents(packet.getNode(), packet.getByteArray()); }
void SpellHandler::HandleMsg( NetworkPacket & recv_data, GameClient *pClient ) { NetworkPacket data; NetworkPacket data2; char f[256]; sprintf(f, "WORLD: Spell 0x%.4X", recv_data.opcode); LOG.outString( f ); switch (recv_data.opcode) { case CMSG_USE_ITEM: { //printf("ok got opcode here %u\n", recv_data.length); uint8 packslot,slot; uint16 targets; uint8 spell; int datalen = recv_data.length; recv_data >> packslot >> slot >> spell; recv_data >> targets; //if (targets == 0) // return; uint32 spellid; //printf("recived data!\n"); //printf("Item ID - %d\nItem GUID - %d\n",pClient->getCurrentChar()->getItemIdBySlot(slot),pClient->getCurrentChar()->getGuidBySlot(slot)); Item *tmpItem = WORLDSERVER.GetItem( pClient->getCurrentChar()->getItemIdBySlot(slot) ); spellid = tmpItem->SpellID[spell - 1]; for(int i = 0;i < 5;i++) { //printf("spell number %d - %d\n",i,tmpItem->SpellID[i]); } data.Clear(); data.Initialize (datalen - 3 + 32, SMSG_SPELL_GO); data << pClient->getCurrentChar()->GetGUID().sno << pClient->getCurrentChar()->GetGUID ().type; data << pClient->getCurrentChar()->GetGUID().sno << pClient->getCurrentChar()->GetGUID ().type; data << uint32(spellid); data << uint8(0x00) << uint8(0x01); if( targets & 0x2 || targets & 0x800 || targets & 0x8000 ) { guid unitTarget; recv_data >> unitTarget.sno >> unitTarget.type; data << uint8(0x01); data << unitTarget.sno << unitTarget.type; data << uint8(0x00); data << uint16(targets); data << unitTarget.sno << unitTarget.type; } SpellInformation spellInfo; //get a hook for the DB DatabaseInterface *dbi = DATABASE.createDatabaseInterface(); //returns a SpellInformation object/struct spellInfo = dbi->GetSpellInformation ( tmpItem->SpellID[0] ); DATABASE.removeDatabaseInterface( dbi ); //clean up used resources if(spellInfo.spell_type == (uint32)POTIONS) usePotion(pClient, tmpItem->SpellID[0], spellInfo, targets); }break; case CMSG_CAST_SPELL: { uint32 spell, target1, target2; uint16 flags; uint8 hitCount ,missCount; recv_data >> spell >> flags; guid pguid = pClient->getCurrentChar()->GetGUID(); SpellInformation spellInfo; //get a hook for the DB DatabaseInterface *dbi = DATABASE.createDatabaseInterface(); spellInfo = dbi->GetSpellInformation ( spell ); //returns a SpellInformation object/struct DATABASE.removeDatabaseInterface( dbi ); //clean up used resources //let's check spell type: if( spellInfo.spell_type == (uint32)SINGLE_TARGET) { recv_data >> target1 >> target2; printf("recv_data >> spell: %u\n", spell); printf("recv_data >> flags: %u\n", flags); Unit* pUnit_target = WORLDSERVER.GetCreature(target1); if(pUnit_target) { if(spellInfo.race == 0 || pUnit_target->getRace() == spellInfo.race) { //if( > spellInfo.Range ){ data.Clear(); data.Initialize( 36, SMSG_SPELL_START ); data << pguid.sno << pguid.type << pguid.sno << pguid.type << spell; data << flags << uint32 (3500) << flags << target1 << target2; pClient->SendMsg( &data ); hitCount = 1; missCount = 0; data2.Clear(); data2.Initialize( 42, SMSG_SPELL_GO ); data2 << pguid.sno << pguid.type << pguid.sno << pguid.type; data2 << spell << uint16 (0x0100) << hitCount << target1 << target2; data2 << missCount << flags << target1 << target2; uint32 damage = spellInfo.DmgPlus1+rand()%spellInfo.RandomPercentDmg; WORLDSERVER.mCombatHandler.AttackerStateUpdate(pClient->getCurrentChar( ), WORLDSERVER.getCreatureMap( )[ target1 ], damage); if(spellInfo.addDuration > 0) { Unit* pCast_target = WORLDSERVER.GetCreature(target1); if( pCast_target ) { uint32 time = spellInfo.addDuration/1000; uint32 addDmg = (uint32)((float)spellInfo.addDmg/(float)time); if(addDmg == 0) addDmg = 1; pCast_target->m_damageDuration = spellInfo.addDuration/1000; pCast_target->m_damage = addDmg; pCast_target->m_Attacker = pClient->getCurrentChar()->GetGUID(); } } uint32 mana = pClient->getCurrentChar()->getUpdateValue( UNIT_FIELD_POWER1 ); pClient->getCurrentChar( )->setUpdateValue( UNIT_FIELD_POWER1, mana-spellInfo.ManaCost ); data.Clear(); data.Initialize( 5, SMSG_CAST_RESULT ); data << spell << uint8( 0x01); pClient->SendMsg( &data ); pClient->getCurrentChar()->SendMessageToSet(&data2, true); } else { data.Clear(); data.Initialize( 6, SMSG_CAST_RESULT ); data << spell << uint8( 0x02); data << uint8(9); pClient->SendMsg( &data ); } } } else if( spellInfo.spell_type == (uint32)MULTI_TARGET )
void NetworkServer::rawSend(const BitStream& bs, const NetworkPacket& packet, const User& user) { assert(isConnected()); sendBitStream(*_peer, bs, packet.params(), user.address()); }