Guest User

Untitled

a guest
Jul 16th, 2015
349
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.51 KB | None | 0 0
  1. void WoWWorldServerClient::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
  2. {
  3.     uint8 utype;
  4.     uint8 hasTransport;
  5.     uint32 usize, ublocks, readblocks = 0;
  6.     uint64 uguid;
  7.     recvPacket >> ublocks; // >> hasTransport;
  8.         recvPacket >> hasTransport;
  9.  
  10.     logdev("UpdateObject: blocks = %u", ublocks);
  11.     while ((recvPacket.rpos() < recvPacket.size()) && (readblocks < ublocks))
  12.     {
  13.         recvPacket >> utype;
  14.         switch (utype)
  15.         {
  16.         case UPDATETYPE_VALUES:
  17.         {
  18.             uguid = recvPacket.readPackGUID();
  19.             _ValuesUpdate(uguid, recvPacket);
  20.         }
  21.         break;
  22.  
  23.         case UPDATETYPE_MOVEMENT:
  24.         {
  25.             recvPacket >> uguid; // the guid is NOT packed here!
  26.             uint8 tyid;
  27.             Object *obj = objmgr.GetObj(uguid, true); // here we update also depleted objects, its just safer
  28.             if (obj)
  29.                 tyid = obj->GetTypeId();
  30.             else // sometimes objects get deleted BEFORE a last update packet arrives, this must be handled also
  31.             {
  32.                 tyid = GetTypeIdByGuid(uguid);
  33.                 logerror("Got UpdateObject_Movement for unknown object "I64FMT". Using typeid %u", uguid, (uint32)tyid);
  34.             }
  35.  
  36.             if (obj)
  37.                 this->_MovementUpdate(tyid, uguid, recvPacket);
  38.         }
  39.         break;
  40.  
  41.         case UPDATETYPE_CREATE_OBJECT2: // will be sent when our very own character is created
  42.         case UPDATETYPE_CREATE_OBJECT: // will be sent on any other object creation
  43.         {
  44.  
  45.             // added by me
  46.             uint8 dummy;
  47.             //recvPacket >> dummy; //0xFF
  48.  
  49.             uguid = recvPacket.readPackGUID();
  50.             //recvPacket >> uguid;
  51.  
  52.  
  53.             uint8 objtypeid;
  54.             recvPacket >> objtypeid;
  55.             logdebug("Create Object type %u with guid "I64FMT, objtypeid, uguid);
  56.             // dont create objects if already present in memory.
  57.             // recreate every object except ourself!
  58.             if (objmgr.GetObj(uguid))
  59.             {
  60.                 if (uguid != GetGuid())
  61.                 {
  62.                     logdev("- already exists, deleting old, creating new object");
  63.                     objmgr.Remove(uguid, false);
  64.                     // do not call script here, since the object does not really get deleted
  65.                 }
  66.                 else
  67.                 {
  68.                     logdev("- already exists, but not deleted (has our current GUID)");
  69.                 }
  70.             }
  71.  
  72.             // only if the obj didnt exist or was just deleted above, create it....
  73.             if (!objmgr.GetObj(uguid))
  74.             {
  75.                 switch (objtypeid)
  76.                 {
  77.                 case TYPEID_OBJECT: // no data to read
  78.                 {
  79.                     logerror("Recieved wrong UPDATETYPE_CREATE_OBJECT to create Object base type!");
  80.                     logerror("%s", toHexDump((uint8*)recvPacket.contents(), recvPacket.size(), true).c_str());
  81.                 }
  82.                 case TYPEID_ITEM:
  83.                 {
  84.                     Item *item = new Item();
  85.                     item->Create(uguid);
  86.                     objmgr.Add(item);
  87.                     logdebug("Created Item with guid "I64FMT, uguid);
  88.                     logdebug("Check: "I64FMT, item->GetGUID());
  89.                     break;
  90.                 }
  91.                 case TYPEID_CONTAINER:
  92.                 {
  93.                     Bag *bag = new Bag();
  94.                     bag->Create(uguid);
  95.                     objmgr.Add(bag);
  96.                     logdebug("Created Bag with guid "I64FMT, uguid);
  97.                     break;
  98.                 }
  99.                 case TYPEID_UNIT:
  100.                 {
  101.                     Unit *unit = new Unit();
  102.                     unit->Create(uguid);
  103.                     objmgr.Add(unit);
  104.                     logdebug("Created Unit with guid "I64FMT, uguid);
  105.                     logdebug("Check: "I64FMT, unit->GetGUID());
  106.                     logdebug("Entry: %i", unit->GetEntry());
  107.                     break;
  108.                 }
  109.                 case TYPEID_PLAYER:
  110.                 {
  111.                     if (GetGuid() == uguid) // objmgr.Add() would cause quite some trouble if we added ourself again
  112.                         break;
  113.                     Player *player = new Player();
  114.                     player->Create(uguid);
  115.                     objmgr.Add(player);
  116.                     logdebug("Created Player with guid "I64FMT, uguid);
  117.                     break;
  118.                 }
  119.                 case TYPEID_GAMEOBJECT:
  120.                 {
  121.                     GameObject *go = new GameObject();
  122.                     go->Create(uguid);
  123.                     objmgr.Add(go);
  124.                     logdebug("Created GO with guid "I64FMT, uguid);
  125.                     break;
  126.                 }
  127.                 case TYPEID_CORPSE:
  128.                 {
  129.                     Corpse *corpse = new Corpse();
  130.                     corpse->Create(uguid);
  131.                     objmgr.Add(corpse);
  132.                     logdebug("Created Corpse with guid "I64FMT, uguid);
  133.                     break;
  134.                 }
  135.                 case TYPEID_DYNAMICOBJECT:
  136.                 {
  137.                     DynamicObject *dobj = new DynamicObject();
  138.                     dobj->Create(uguid);
  139.                     objmgr.Add(dobj);
  140.                     logdebug("Created DynObj with guid "I64FMT, uguid);
  141.                     break;
  142.                 }
  143.                 }
  144.             }
  145.             else
  146.             {
  147.                 logdebug("Obj "I64FMT" not created, already exists", uguid);
  148.             }
  149.             // ...regardless if it was freshly created or already present, update its values and stuff now...
  150.             this->_MovementUpdate(objtypeid, uguid, recvPacket);
  151.             this->_ValuesUpdate(uguid, recvPacket);
  152.  
  153.             // ...and ask the server for eventually missing data.
  154.             _QueryObjectInfo(uguid);
  155.  
  156.  
  157.             // call script "_OnObjectCreate"
  158.             //if (GetInstance()->GetScripts()->ScriptExists("_onobjectcreate"))
  159.             //{
  160.             //  CmdSet Set;
  161.             //  Set.defaultarg = toString(uguid);
  162.             //  Set.arg[0] = toString(objtypeid);
  163.             //  GetInstance()->GetScripts()->RunScript("_onobjectcreate", &Set);
  164.  
  165.             //}
  166.  
  167.             // if our own character got finally created, we have successfully entered the world,
  168.             // and should have gotten all info about our char already.
  169.         }
  170.         break;
  171.  
  172.         case UPDATETYPE_OUT_OF_RANGE_OBJECTS:
  173.         {
  174.             recvPacket >> usize;
  175.             for (uint32 i = 0; i<usize; i++)
  176.             {
  177.                 uguid = recvPacket.readPackGUID(); // not 100% sure if this is correct
  178.                 logdebug("GUID "I64FMT" out of range", uguid);
  179.  
  180.                 //                     // call script just before object removal
  181.                 //                     if(GetInstance()->GetScripts()->ScriptExists("_onobjectdelete"))
  182.                 //                     {
  183.                 //                         Object *del_obj = objmgr.GetObj(uguid);
  184.                 //                         CmdSet Set;
  185.                 //                         Set.defaultarg = toString(uguid);
  186.                 //                         Set.arg[0] = del_obj ? toString(del_obj->GetTypeId()) : "";
  187.                 //                         Set.arg[1] = "true"; // out of range = true
  188.                 //                         GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set);
  189.                 //                     }
  190.                 //
  191.                 //                     objmgr.Remove(uguid, false);
  192.             }
  193.         }
  194.         break;
  195.  
  196.         default:
  197.         {
  198.             logerror("UPDATE_OBJECT: Got unk updatetype 0x%X", utype);
  199.             logerror("UPDATE_OBJECT: Read %u / %u bytes, skipped rest", recvPacket.rpos(), recvPacket.size());
  200.             logerror("%s", toHexDump((uint8*)recvPacket.contents(), recvPacket.size(), true).c_str());
  201.             char buf[100];
  202.             sprintf(buf, "Got unk updatetype=0x%X, read %u / %u bytes", utype, recvPacket.rpos(), recvPacket.size());
  203.  
  204.             //if (GetInstance()->GetConf()->dumpPackets)
  205.             //{
  206.             //  char buf[100];
  207.             //  sprintf(buf, "Got unk updatetype=0x%X, read %u / %u bytes", utype, recvPacket.rpos(), recvPacket.size());
  208.             //  DumpPacket(recvPacket, recvPacket.rpos(), buf);
  209.             //}
  210.  
  211.             return;
  212.         }
  213.         } // switch
  214.         readblocks++;
  215.     } // while
  216.  
  217. } // func
  218.  
  219. void WoWWorldServerClient::_MovementUpdate(uint8 objtypeid, uint64 uguid, WorldPacket& recvPacket)
  220. {
  221.     MovementInfo mi; // TODO: use a reference to a MovementInfo in Unit/Player class once implemented
  222.     uint16 flags;
  223.     uint8 flags_6005;
  224.     // uint64 fullguid; // see below
  225.     float speedWalk =0, speedRun =0, speedSwimBack =0, speedSwim =0, speedWalkBack =0, speedTurn =0, speedFly =0, speedFlyBack =0, speedPitchRate =0;
  226.     uint32 unk32;
  227.  
  228.     Object *obj = (Object*)objmgr.GetObj(uguid, true); // also depleted objects
  229.     Unit *u = NULL;
  230.     if(obj)
  231.     {
  232.         if(obj->IsUnit())
  233.             u = (Unit*)obj; // only use for Unit:: functions!!
  234.         else
  235.             logdev("MovementUpdate: object "I64FMT" is not Unit (typeId=%u)",obj->GetGUID(),obj->GetTypeId());
  236.     }
  237.     else
  238.     {
  239.         logerror("MovementUpdate for unknown object "I64FMT" typeid=%u",uguid,objtypeid);
  240.     }
  241.  
  242.     //if (client > CLIENT_TBC)
  243. //      recvPacket >> flags;
  244.     //else
  245.     //{
  246.         recvPacket >> flags_6005;
  247.         flags = flags_6005;
  248.     //}
  249.  
  250.     mi.flags = 0; // not sure if its correct to set it to 0 (needs some starting flag?)
  251.     if(flags & UPDATEFLAG_LIVING)
  252.     {
  253.         recvPacket >> mi;
  254.  
  255.         logdev("MovementUpdate: TypeID=%u GUID="I64FMT" pObj=%X flags=%x mi.flags=%x",objtypeid,uguid,obj,flags,mi.flags);
  256.         logdev("FLOATS: x=%f y=%f z=%f o=%f",mi.pos.x, mi.pos.y, mi.pos.z ,mi.pos.o);
  257.         if(obj && obj->IsWorldObject())
  258.             ((WorldObject*)obj)->SetPosition(mi.pos.x, mi.pos.y, mi.pos.z, mi.pos.o);
  259.  
  260.         if(mi.flags & MOVEMENTFLAG_ONTRANSPORT)
  261.         {
  262.             logdev("TRANSPORT @ mi.flags: guid="I64FMT" x=%f y=%f z=%f o=%f", mi.t_guid, mi.t_pos.x, mi.t_pos.y, mi.t_pos.z, mi.t_pos.o);
  263.         }
  264.  
  265.         if((mi.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi.flags2 & MOVEMENTFLAG2_ALLOW_PITCHING))
  266.         {
  267.             logdev("MovementUpdate: MOVEMENTFLAG_SWIMMING or FLYING is set, angle = %f!", mi.s_angle);
  268.         }
  269.  
  270.         logdev("MovementUpdate: FallTime = %u", mi.fallTime);
  271.  
  272.         if(mi.flags & MOVEMENTFLAG_FALLING)
  273.         {
  274.             logdev("MovementUpdate: MOVEMENTFLAG_FALLING is set, velocity=%f sinA=%f cosA=%f xyspeed=%f = %u", mi.j_velocity, mi.j_sinAngle, mi.j_cosAngle, mi.j_xyspeed);
  275.         }
  276.  
  277.         if(mi.flags & MOVEMENTFLAG_SPLINE_ELEVATION)
  278.         {
  279.             logdev("MovementUpdate: MOVEMENTFLAG_SPLINE is set, got %u", mi.u_unk1);
  280.         }
  281.  
  282.         recvPacket >> speedWalk >> speedRun >> speedSwimBack >> speedSwim >> speedWalkBack; // speedRun can also be mounted speed if player is mounted; WalkBack is called RunBack in Mangos
  283.  
  284.         recvPacket >> speedFly >> speedFlyBack; // fly added in 2.0.x
  285.         recvPacket >> speedTurn;
  286.  
  287.         logdev("MovementUpdate: Got speeds, walk=%f run=%f turn=%f", speedWalk, speedRun, speedTurn);
  288.         if(u)
  289.         {
  290.             u->SetPosition(mi.pos.x, mi.pos.y, mi.pos.z, mi.pos.o);
  291.             u->SetSpeed(MOVE_WALK, speedWalk);
  292.             u->SetSpeed(MOVE_RUN, speedRun);
  293.             u->SetSpeed(MOVE_SWIMBACK, speedSwimBack);
  294.             u->SetSpeed(MOVE_SWIM, speedSwim);
  295.             u->SetSpeed(MOVE_WALKBACK, speedWalkBack);
  296.             u->SetSpeed(MOVE_TURN, speedTurn);
  297.             u->SetSpeed(MOVE_FLY, speedFly);
  298.             u->SetSpeed(MOVE_FLYBACK, speedFlyBack);
  299.             u->SetSpeed(MOVE_PITCH_RATE, speedPitchRate);
  300.         }
  301.  
  302.         // TODO: correct this one as soon as its meaning is known OR if it appears often and needs to be fixed
  303.         if(mi.flags & MOVEMENTFLAG_SPLINE_ENABLED)
  304.         {
  305.             logdev("MovementUpdate: MOVEMENTFLAG_SPLINE_ENABLED!");
  306.             //checked for 3.3.5
  307.             //We do not do anything with the spline stuff so far, it just needs to be read to be skipped correctly
  308.             uint32 splineflags, timepassed, duration, id, effect_start_time, path_nodes;
  309.             uint8 spline_mode;
  310.             float facing_angle,facing_x,facing_y,facing_z, duration_mod, duration_next, vertical_acceleration;
  311.             float x,y,z;
  312.             uint64 facing_target;
  313.             recvPacket >> splineflags;
  314.             if(splineflags & SF_Final_Angle)
  315.               recvPacket >> facing_angle;
  316.             if(splineflags & SF_Final_Point)
  317.               recvPacket >> facing_x >> facing_y >> facing_z;
  318.             recvPacket >> timepassed >> duration >> id >> duration_mod >> duration_next >> vertical_acceleration >> effect_start_time;
  319.             recvPacket >> path_nodes;
  320.             for(uint32 i = 0;i<path_nodes;i++)
  321.             {
  322.               recvPacket >> x >> y >> z;
  323.             }
  324.             recvPacket >> spline_mode;
  325.             recvPacket >> x >> y >> z; // FinalDestination
  326.         }
  327.     }
  328.     else // !UPDATEFLAG_LIVING
  329.     {
  330.         if(flags & UPDATEFLAG_POSITION)
  331.         {
  332.             uint64 pguid = recvPacket.readPackGUID();
  333.             float x,y,z,o,sx,sy,sz,so;
  334.             recvPacket >> x >> y >> z;
  335.             recvPacket >> sx >> sy >> sz;
  336.             recvPacket >> o >> so;
  337.  
  338.             if (obj && obj->IsWorldObject())
  339.                 ((WorldObject*)obj)->SetPosition(x, y, z, o);
  340.         }
  341.         else
  342.         {
  343.             if(flags & UPDATEFLAG_HAS_POSITION)
  344.             {
  345.                 float x,y,z,o;
  346.                 if(flags & UPDATEFLAG_TRANSPORT)
  347.                 {
  348.                     recvPacket >> x >> y >> z >> o;
  349.                     // only zeroes here
  350.                 }
  351.                 else
  352.                 {
  353.                     recvPacket >> x >> y >> z >> o;
  354.                     if (obj && obj->IsWorldObject())
  355.                         ((WorldObject*)obj)->SetPosition(x, y, z, o);
  356.                 }
  357.             }
  358.         }
  359.     }
  360.  
  361.         recvPacket >> unk32;
  362.         logdev("MovementUpdate: UPDATEFLAG_LOWGUID is set, got %X", unk32);
  363.    
  364.  
  365.  
  366.         recvPacket >> unk32;             // 2.0.6 - high guid was there, unk for 2.0.12
  367.         // not sure if this is correct, MaNGOS sends 0 always.
  368.         //obj->SetUInt32Value(OBJECT_FIELD_GUID+1,higuid); // note that this sets only the high part of the guid
  369.         logdev("MovementUpdate: UPDATEFLAG_HIGHGUID is set, got %X", unk32);
  370.    
  371.  
  372.         recvPacket >> unk32;
  373.         // MaNGOS sends 1 always.
  374.         logdev("MovementUpdate: UPDATEFLAG_ALL is set, got %X", unk32);
  375.    
  376.  
  377.  
  378.     if(flags & UPDATEFLAG_HAS_TARGET)
  379.     {
  380.         uint64 unkguid = recvPacket.readPackGUID(); // MaNGOS sends uint8(0) always, but its probably be a packed guid
  381.         logdev("MovementUpdate: UPDATEFLAG_FULLGUID is set, got "I64FMT, unkguid);
  382.     }
  383.  
  384.     if(flags & UPDATEFLAG_TRANSPORT)
  385.     {
  386.         recvPacket >> unk32; // mangos says: ms time
  387.         logdev("MovementUpdate: UPDATEFLAG_TRANSPORT is set, got %u", unk32);
  388.     }
  389.  
  390.     if(flags & UPDATEFLAG_VEHICLE)                          // unused for now
  391.     {
  392.         uint32 vehicleId;
  393.         float facingAdj;
  394.  
  395.         recvPacket >> vehicleId >> facingAdj;
  396.     }
  397.  
  398.     if(flags & UPDATEFLAG_ROTATION)
  399.     {
  400.         uint64 rotation;
  401.         recvPacket >> rotation;
  402.         // gameobject rotation
  403.     }
  404. }
  405.  
  406. void WoWWorldServerClient::_ValuesUpdate(uint64 uguid, WorldPacket& recvPacket)
  407. {
  408.     Object *obj = objmgr.GetObj(uguid);
  409.     uint8 blockcount, tyid;
  410.     uint32 value, masksize, valuesCount;
  411.  
  412.     if (obj)
  413.     {
  414.         valuesCount = obj->GetValuesCount();
  415.         tyid = obj->GetTypeId();
  416.         logdebug("Type %u Object, %u Values", tyid, valuesCount);
  417.     }
  418.     else
  419.     {
  420.         logcustom(1, LRED, "Got UpdateObject_Values for unknown object "I64FMT, uguid);
  421.         tyid = GetTypeIdByGuid(uguid); // can cause problems with TYPEID_CONTAINER!!
  422.         valuesCount = GetValuesCountByTypeId(tyid);
  423.     }
  424.  
  425.  
  426.     recvPacket >> blockcount;
  427.     masksize = blockcount << 2; // each sizeof(uint32) == <4> * sizeof(uint8) // 1<<2 == <4>
  428.     UpdateMask umask;
  429.     uint32 *updateMask = new uint32[blockcount];
  430.     umask.SetCount(masksize);
  431.     recvPacket.read((uint8*)updateMask, masksize);
  432.     umask.SetMask(updateMask);
  433.     //delete [] updateMask; // will be deleted at ~UpdateMask() !!!!
  434.     logdev("ValuesUpdate TypeId=%u GUID="I64FMT" pObj=%X Blocks=%u Masksize=%u", tyid, uguid, obj, blockcount, masksize);
  435.     // just in case the object does not exist, and we have really a container instead of an item, and a value in
  436.     // the container fields is set, THEN we have a problem. this should never be the case; it can be fixed in a
  437.     // more correct way if there is the need.
  438.     // (-> valuesCount smaller then it should be might skip a few bytes and corrupt the packet)
  439.     for (uint32 i = 0; i < valuesCount; i++)
  440.     {
  441.         if (umask.GetBit(i))
  442.         {
  443.             if (obj)
  444.             {
  445.                 recvPacket >> value;
  446.                 obj->SetUInt32Value(i, value);  //It does not matter what type of value we are setting, just copy the bytes
  447.                 //DEBUG(logdev("Setting value: %u = %u (i)", i, value, value));
  448.                 logdebug("Value set %i = %i", i, value);
  449.             }
  450.             else
  451.             {
  452.                 recvPacket >> value; // drop the value, since object doesnt exist (always 4 bytes)
  453.                 logdebug("Obj doesnt exist when setting values!");
  454.             }
  455.         }
  456.         //else logdebug("umask = false");
  457.     }
  458. }
Advertisement
Add Comment
Please, Sign In to add comment