www.pudn.com > boogiebot.zip > WorldServerClient.Object.cs
#undef DEBUG
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Xml;
using System.Timers;
using System.IO;
using Foole.Crypt;
using Foole.Utils;
using Foole.WoW;
namespace BoogieBot.Common
{
// WoWObject Packet Handling
partial class WorldServerClient
{
private void Handle_ObjUpdate(WoWReader wr, bool Compressed)
{
if (Compressed)
{
Int32 size = wr.ReadInt32();
byte[] decomped = Foole.Utils.Compression.Decompress(size, wr.ReadRemaining());
wr = new WoWReader(decomped);
}
WoWGuid guid;
UInt32 blockCount;
byte unk1;
byte blockType;
byte objTypeId;
blockCount = wr.ReadUInt32();
unk1 = wr.ReadByte();
//BoogieCore.Log("Got obj update with {0} blocks", blockCount);
for (UInt32 i = 0; i < blockCount; i++)
{
blockType = wr.ReadByte();
switch (blockType)
{
case 0: // Fields update
{
byte mask = wr.ReadByte();
if (mask == 0x00)
break;
guid = new WoWGuid(mask, wr.ReadBytes(WoWGuid.BitCount8(mask)));
UpdateMask UpdateMask = new UpdateMask();
byte bc = wr.ReadByte(); // Block Count
UpdateMask.SetCount((ushort)(bc * 32));
UpdateMask.SetMask(wr.ReadBytes(bc * 4), bc);
#if (DEBUG)
BoogieCore.Log("Field Update! FieldCount: {0}", UpdateMask.GetCount());
#endif
UInt32[] Fields = new UInt32[UpdateMask.GetCount()];
Object obj = BoogieCore.World.getObject(guid);
if (obj == null)
{
BoogieCore.Log(LogType.Error, "Object with the guid {0} not recognized in field update.", guid.GetOldGuid());
}
for (ushort x = 0; x < UpdateMask.GetCount(); x++)
{
if (UpdateMask.GetBit(x))
if (obj == null) // FixMe
wr.ReadUInt32();
else
obj.Fields[x] = wr.ReadUInt32();
}
// Update Player Class if these are Player Fields being changed.
if (obj != null)
if (obj.GUID.GetOldGuid() == BoogieCore.Player.Character.GUID)
BoogieCore.Player.updatePlayer(obj);
break;
}
case 1: // Movement Update
{
byte mask = wr.ReadByte();
if (mask == 0x00)
break;
guid = new WoWGuid(mask, wr.ReadBytes(WoWGuid.BitCount8(mask)));
BoogieCore.Log(LogType.NeworkComms, "Got Movement update for GUID {0}", BitConverter.ToUInt64(guid.GetNewGuid(), 0));
UInt32 flags2 = 0, unk3;
float posX, posY, posZ, facing;
float walkSpeed, runSpeed, backWalkSpeed, swimSpeed, backSwimSpeed, turnRate;
byte flags = wr.ReadByte();
if ((flags & 32) >= 1)
{
flags2 = wr.ReadUInt32();
unk3 = wr.ReadUInt32();
}
if ((flags & 0x40) >= 1)
{
posX = wr.ReadSingle();
posY = wr.ReadSingle();
posZ = wr.ReadSingle();
facing = wr.ReadSingle();
BoogieCore.Log(LogType.NeworkComms, "Position - X: {0} Y: {1} Z: {2} Orient: {3} ", posX, posY, posZ, facing);
if ((flags2 & 0x02000000) >= 1) // player being transported
{
BoogieCore.Log(LogType.NeworkComms, "(flags2 & 0x02000000)");
wr.ReadUInt32(); //guidlow
wr.ReadUInt32(); //guidhigh
wr.ReadSingle(); //x
wr.ReadSingle(); //y
wr.ReadSingle(); //z
wr.ReadSingle(); //o
}
}
if ((flags & 0x20) >= 1)
{
wr.ReadSingle(); //unk
if ((flags2 & 0x2000) >= 1)
{
wr.ReadSingle(); // pos unk1
wr.ReadSingle(); // pos unk1
wr.ReadSingle(); // pos unk1
wr.ReadSingle(); // pos unk1
//BoogieCore.Log(LogType.NeworkComms, "Position 2 - X: {0} Y: {1} Z: {2} Orient: {3} ", punk1, punk2, punk3, punk1);
}
}
if ((flags & 32) >= 1)
{
walkSpeed = wr.ReadSingle();
runSpeed = wr.ReadSingle();
backWalkSpeed = wr.ReadSingle();
swimSpeed = wr.ReadSingle();
backSwimSpeed = wr.ReadSingle();
wr.ReadSingle(); //unk1
wr.ReadSingle(); //unk2
turnRate = wr.ReadSingle();
}
if ((flags & 0x20) >= 1)
{
if ((flags2 & 0x00400000) >= 1)
{
UInt32 splineFlags;
splineFlags = wr.ReadUInt32();
if ((splineFlags & 0x00010000) >= 1)
{
posX = wr.ReadSingle();
posY = wr.ReadSingle();
posZ = wr.ReadSingle();
}
if ((splineFlags & 0x00020000) >= 1)
{
UInt64 v;
v = wr.ReadUInt64();
}
if ((splineFlags & 0x00040000) >= 1)
{
float f;
f = wr.ReadSingle();
}
UInt32 time1, time2, splineCount, unk4;
//1.8
time1 = wr.ReadUInt32();
time2 = wr.ReadUInt32();
unk4 = wr.ReadUInt32();
splineCount = wr.ReadUInt32();
for (UInt32 j = 0; j < splineCount + 1; j++)
{
posX = wr.ReadSingle();
posY = wr.ReadSingle();
posZ = wr.ReadSingle();
}
}
}
if ((flags & 0x2) >= 1)
{
UInt32 assoc;
assoc = wr.ReadUInt32();
}
UInt32 weirdunk = wr.ReadUInt32();
if ((flags & 0x04) >= 1)
{
wr.ReadBytes(8);
}
break;
}
case 2: // ObjCreate
case 3: // ObjCreate
{
byte mask = wr.ReadByte();
guid = new WoWGuid(mask, wr.ReadBytes(WoWGuid.BitCount8(mask)));
objTypeId = wr.ReadByte();
BoogieCore.Log(LogType.NeworkComms, "Got Object Create Mask: 0x{0:x2} GUID: {1} ObjTypeID: {2} ", mask, BitConverter.ToUInt64(guid.GetNewGuid(), 0), objTypeId);
UInt32 flags2 = 0, unk3;
float posX = 0;
float posY = 0;
float posZ = 0;
float facing = 0;
float walkSpeed, runSpeed, backWalkSpeed, swimSpeed, backSwimSpeed, turnRate = 0;
byte flags = wr.ReadByte();
if ((flags & 0x20) >= 1)
{
flags2 = wr.ReadUInt32();
unk3 = wr.ReadUInt32();
}
if ((flags & 0x40) >= 1)
{
posX = wr.ReadSingle();
posY = wr.ReadSingle();
posZ = wr.ReadSingle();
facing = wr.ReadSingle();
BoogieCore.Log(LogType.NeworkComms, "Position - X: {0} Y: {1} Z: {2} Orient: {3} ", posX, posY, posZ, facing);
if ((flags2 & 0x02000000) >= 1) // player being transported
{
BoogieCore.Log(LogType.NeworkComms, "(flags2 & 0x02000000)");
wr.ReadUInt32(); //guidlow
wr.ReadUInt32(); //guidhigh
wr.ReadSingle(); //x
wr.ReadSingle(); //y
wr.ReadSingle(); //z
wr.ReadSingle(); //o
}
}
if ((flags & 0x20) >= 1)
{
wr.ReadSingle(); //unk
if ((flags2 & 0x2000) >= 1)
{
wr.ReadSingle(); // pos unk1
wr.ReadSingle(); // pos unk1
wr.ReadSingle(); // pos unk1
wr.ReadSingle(); // pos unk1
//BoogieCore.Log(LogType.NeworkComms, "Position 2 - X: {0} Y: {1} Z: {2} Orient: {3} ", punk1, punk2, punk3, punk1);
}
}
if ((flags & 0x20) >= 1)
{
walkSpeed = wr.ReadSingle();
runSpeed = wr.ReadSingle();
backWalkSpeed = wr.ReadSingle();
swimSpeed = wr.ReadSingle();
backSwimSpeed = wr.ReadSingle();
wr.ReadSingle(); //unk1
wr.ReadSingle(); //unk2
turnRate = wr.ReadSingle();
BoogieCore.Log(LogType.NeworkComms, "Speed - (flags & 0x20)");
}
if ((flags & 0x20) >= 1)
{
BoogieCore.Log(LogType.NeworkComms, "(flags & 0x20)");
if ((flags2 & 0x00400000) >= 1)
{
BoogieCore.Log(LogType.NeworkComms, "(flags2 & 0x00400000)");
UInt32 splineFlags;
splineFlags = wr.ReadUInt32();
if ((splineFlags & 0x00010000) >= 1)
{
BoogieCore.Log(LogType.NeworkComms, "(splineFlags & 0x00010000)");
posX = wr.ReadSingle();
posY = wr.ReadSingle();
posZ = wr.ReadSingle();
BoogieCore.Log(LogType.NeworkComms, "Position 3 - X: {0} Y: {1} Z: {2} Orient: {3} ", posX, posY, posZ, facing);
}
if ((splineFlags & 0x00020000) >= 1)
{
BoogieCore.Log(LogType.NeworkComms, "(splineFlags & 0x00020000)");
wr.ReadUInt64();
}
if ((splineFlags & 0x00040000) >= 1)
{
BoogieCore.Log(LogType.NeworkComms, "(splineFlags & 0x00040000)");
float f;
f = wr.ReadSingle();
}
UInt32 time1, time2, splineCount, unk4;
//1.8
time1 = wr.ReadUInt32();
time2 = wr.ReadUInt32();
unk4 = wr.ReadUInt32();
splineCount = wr.ReadUInt32();
BoogieCore.Log(LogType.NeworkComms, "splineCount = {0}", splineCount);
for (UInt32 j = 0; j < splineCount + 1; j++)
{
posX = wr.ReadSingle();
posY = wr.ReadSingle();
posZ = wr.ReadSingle();
//BoogieCore.Log(LogType.NeworkComms, "Position 4 - X: {0} Y: {1} Z: {2} Orient: {3} ", posX, posY, posZ, facing);
}
}
}
if ((flags & 0x8) >= 1)
{
wr.ReadUInt32();
if ((flags & 0x10) >= 1)
wr.ReadUInt32();
}
if ((flags & 0x2) >= 1)
{
BoogieCore.Log(LogType.NeworkComms, "(flags & 0x2)");
wr.ReadUInt32();
}
UpdateMask UpdateMask = new UpdateMask();
byte bc = wr.ReadByte(); // Block Count
UpdateMask.SetCount((ushort)(bc * 32));
UpdateMask.SetMask(wr.ReadBytes(bc * 4), bc);
if (UpdateMask.GetCount() > 1500)
{
int count = UpdateMask.GetCount();
BoogieCore.Log(LogType.Error, "Bad mask count = {0} ! aborting parse", count);
return;
}
BoogieCore.Log(LogType.NeworkComms, "(ObjCreate) FieldCount: {0}", UpdateMask.GetCount());
UInt32[] Fields = new UInt32[UpdateMask.GetCount()];
for (ushort x = 0; x < UpdateMask.GetCount(); x++)
{
if (UpdateMask.GetBit(x))
Fields[x] = wr.ReadUInt32();
}
if (!BoogieCore.world.objectExists(guid)) // Add new Object
{
UInt32 entryid = Fields[(int)UpdateFields.OBJECT_FIELD_ENTRY];
Object NewObj = new Object();
NewObj.GUID = guid;
NewObj.coord = new Coordinate(posX, posY, posZ, facing);
NewObj.Type = flags;
NewObj.Fields = Fields;
//GetTile(posX, posY); // This does nothing?
BoogieCore.world.newObject(NewObj, false);
if (objTypeId == 4)
{
QueryName(guid);
BoogieCore.Log(LogType.NeworkComms, "Adding new Player {0}", BitConverter.ToUInt64(guid.GetNewGuid(), 0));
}
if (objTypeId == 3 || objTypeId == 5)
{
BoogieCore.Log(LogType.System, "Querying for name of object with an entry of {0} and type of {1}", entryid, objTypeId);
if (EntryList.ContainsKey(entryid) == false && EntryQueue.ContainsKey(entryid) == false)
{
EntryQueue.Add(entryid, true);
if (objTypeId == 3)
{
WoWWriter wr2 = CreatureQuery(guid, entryid);
Send(wr2.ToArray());
BoogieCore.Log(LogType.NeworkComms, "Adding new Unit {0}", BitConverter.ToUInt64(guid.GetNewGuid(), 0));
}
if (objTypeId == 5)
{
WoWWriter wr2 = GameObjectQuery(guid, entryid);
Send(wr2.ToArray());
BoogieCore.Log(LogType.NeworkComms, "Adding new GameObject {0}", BitConverter.ToUInt64(guid.GetNewGuid(), 0));
}
}
}
}
else // Update Existing Object
{
Object updateObj = BoogieCore.world.getObject(guid);
updateObj.coord = new Coordinate(posX, posY, posZ, facing);
updateObj.Type = flags;
updateObj.Fields = Fields;
BoogieCore.world.updateObject(updateObj);
}
break;
}
case 4: // Out Of Range update
{
UInt32 count = wr.ReadUInt32();
for (UInt32 j = 0; j < count; j++)
{
byte mask = wr.ReadByte();
guid = new WoWGuid(mask, wr.ReadBytes(WoWGuid.BitCount8(mask)));
BoogieCore.world.delObject(guid);
}
break;
}
}
}
}
//private void GetTile(float x, float y)
//{
// float X, Y;
// X = (x + (32.0f * 533.33333f));
// Y = (y + (32.0f * 533.33333f));
// int gx = (int)((x + (32.0f * 533.33333f)) / 533.33333f);
// int gy = (int)(Y / 533.33333f);
//}
private void Handle_ObjDestroy(WoWReader wr)
{
WoWGuid guid = new WoWGuid(wr.ReadUInt64());
BoogieCore.world.delObject(guid);
}
private void Handle_GameObjectQuery(WoWReader wr)
{
Entry entry = new Entry();
entry.entry = wr.ReadUInt32();
if (entry.entry < 1 || wr.Remaining < 4)
{
BoogieCore.Log(LogType.System, "Got {1} in GameObject query response for entryid or remaining in packet too small {0}", wr.Remaining, entry.entry);
return;
}
entry.Type = wr.ReadUInt32();
entry.DisplayID = wr.ReadUInt32();
entry.name = wr.ReadString();
BoogieCore.Log(LogType.NeworkComms, "Got GameObject Query Response - Entry: {0} - Name: {1} - Type {2}", entry.entry, entry.name, entry.Type);
if (EntryList.ContainsKey(entry.entry) == false)
EntryList.Add(entry.entry, entry);
if (EntryQueue.ContainsKey(entry.entry))
EntryQueue.Remove(entry.entry);
foreach (Object obj in BoogieCore.world.getObjectList())
{
if (obj.Fields != null)
{
if (obj.Fields[(int)UpdateFields.OBJECT_FIELD_ENTRY] == entry.entry)
{
obj.Type = (byte)entry.Type;
obj.Name = entry.name;
}
}
}
}
private void Handle_CreatureQuery(WoWReader wr)
{
Entry entry = new Entry();
entry.entry = wr.ReadUInt32();
entry.name = wr.ReadString();
entry.blarg = wr.ReadBytes(3);
entry.subname = wr.ReadString();
entry.flags = wr.ReadUInt32();
entry.subtype = wr.ReadUInt32();
entry.family = wr.ReadUInt32();
entry.rank = wr.ReadUInt32();
BoogieCore.Log(LogType.NeworkComms, "Got CreatureQuery Response - Entry: {0} - Name: {1} - SubName {2}", entry.entry, entry.name, entry.subname);
if (EntryList.ContainsKey(entry.entry) == false)
EntryList.Add(entry.entry, entry);
if (EntryQueue.ContainsKey(entry.entry))
EntryQueue.Remove(entry.entry);
foreach (Object obj in BoogieCore.world.getObjectList())
{
if (obj.Fields != null)
{
if (obj.Fields[(int)UpdateFields.OBJECT_FIELD_ENTRY] == entry.entry)
{
if (entry.name.Contains("Auctioneer") && SentHello == false)
{
WoWWriter ww = new WoWWriter(OpCode.MSG_AUCTION_HELLO);
ww.Write(obj.GUID.GetOldGuid());
Send(ww.ToArray());
BoogieCore.Log(LogType.SystemDebug, "Sent AH Hello!");
SentHello = true;
}
obj.Name = entry.name;
obj.SubName = entry.subname;
obj.SubType = entry.subtype;
obj.Family = entry.family;
obj.Rank = entry.rank;
}
}
}
}
public void QueryName(WoWGuid guid)
{
WoWWriter wr = new WoWWriter(OpCode.CMSG_NAME_QUERY);
wr.Write(guid.GetOldGuid());
Send(wr.ToArray());
}
public void QueryName(UInt64 guid)
{
WoWWriter wr = new WoWWriter(OpCode.CMSG_NAME_QUERY);
wr.Write(guid);
Send(wr.ToArray());
}
public WoWWriter CreatureQuery(WoWGuid guid, UInt32 entry)
{
WoWWriter wr = new WoWWriter(OpCode.CMSG_CREATURE_QUERY);
wr.Write(entry);
wr.Write(guid.GetOldGuid());
return wr;
}
public WoWWriter GameObjectQuery(WoWGuid guid, UInt32 entry)
{
WoWWriter wr = new WoWWriter(OpCode.CMSG_GAMEOBJECT_QUERY);
wr.Write(entry);
wr.Write(guid.GetOldGuid());
return wr;
}
private float GetDistance2dSq(Object obj)
{
Object mObj = BoogieCore.world.getPlayerObject();
float dx = obj.coord.X - mObj.coord.X;
float dy = obj.coord.Y - mObj.coord.Y;
return (dx*dx) + (dy*dy);
}
private void Handle_NameQuery(WoWReader wr)
{
WoWGuid guid = new WoWGuid(wr.ReadUInt64());
string name = wr.ReadString();
UInt16 unk = wr.ReadByte();
UInt32 Race = wr.ReadUInt32();
UInt32 Gender = wr.ReadUInt32();
UInt32 Level = wr.ReadUInt32();
BoogieCore.Log(LogType.NeworkComms, "Got NameQuery Response - GUID: {4} Name: {0} - Race: {1} - Gender: {2} - Level: {3}", name, Race, Gender, Level, BitConverter.ToUInt64(guid.GetNewGuid(), 0));
Object obj = BoogieCore.world.getObject(guid);
if (obj != null) // Update existing object
{
obj.Name = name;
obj.Race = Race;
obj.Gender = Gender;
obj.Level = Level;
BoogieCore.world.updateObject(obj);
}
else // Create new Object -- FIXME: Add to new 'names only' list?
{
obj = new Object();
obj.GUID = guid;
obj.Name = name;
obj.Race = Race;
obj.Gender = Gender;
obj.Level = Level;
BoogieCore.world.newObject(obj, true);
}
/* Process chat message if we looked them up now */
for (int i = 0; i < ChatQueued.Count; i++)
{
ChatQueue message = (ChatQueue)ChatQueued[i];
if (message.GUID.GetOldGuid() == guid.GetOldGuid())
{
BoogieCore.Event(new Event(EventType.EVENT_CHAT, Time.GetTime(), message, name));
ChatQueued.Remove(message);
}
}
// WoWChat uses this to retrive names on friends and ignore list.
BoogieCore.Event(new Event(EventType.EVENT_NAMEQUERY_RESPONSE, Time.GetTime(), guid, name));
}
}
public struct Entry
{
public UInt32 Type;
public UInt32 DisplayID;
public UInt32 entry;
public string name;
public byte[] blarg;
public string subname;
public UInt32 flags;
public UInt32 subtype;
public UInt32 family;
public UInt32 rank;
}
}