protected void ObjectUpdateCompressedHandler(object sender, PacketReceivedEventArgs e)
{
Packet packet = e.Packet;
Simulator simulator = e.Simulator;
ObjectUpdateCompressedPacket update = (ObjectUpdateCompressedPacket)packet;
for (int b = 0; b < update.ObjectData.Length; b++)
{
ObjectUpdateCompressedPacket.ObjectDataBlock block = update.ObjectData[b];
int i = 0;
try
{
// UUID
UUID FullID = new UUID(block.Data, 0);
i += 16;
// Local ID
uint LocalID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
(block.Data[i++] << 16) + (block.Data[i++] << 24));
// PCode
PCode pcode = (PCode)block.Data[i++];
#region Relevance check
if (!Client.Settings.ALWAYS_DECODE_OBJECTS)
{
switch (pcode)
{
case PCode.Grass:
case PCode.Tree:
case PCode.NewTree:
case PCode.Prim:
if (m_ObjectUpdate == null) continue;
break;
}
}
#endregion Relevance check
bool isNew;
lock (simulator.ObjectsPrimitives.Dictionary)
isNew = !simulator.ObjectsPrimitives.ContainsKey(LocalID);
Primitive prim = GetPrimitive(simulator, LocalID, FullID);
prim.LocalID = LocalID;
prim.ID = FullID;
prim.Flags = (PrimFlags)block.UpdateFlags;
prim.PrimData.PCode = pcode;
#region Decode block and update Prim
// State
prim.PrimData.State = block.Data[i++];
// CRC
i += 4;
// Material
prim.PrimData.Material = (Material)block.Data[i++];
// Click action
prim.ClickAction = (ClickAction)block.Data[i++];
// Scale
prim.Scale = new Vector3(block.Data, i);
i += 12;
// Position
prim.Position = new Vector3(block.Data, i);
i += 12;
// Rotation
prim.Rotation = new Quaternion(block.Data, i, true);
i += 12;
// Compressed flags
CompressedFlags flags = (CompressedFlags)Utils.BytesToUInt(block.Data, i);
i += 4;
prim.OwnerID = new UUID(block.Data, i);
i += 16;
// Angular velocity
if ((flags & CompressedFlags.HasAngularVelocity) != 0)
{
prim.AngularVelocity = new Vector3(block.Data, i);
i += 12;
}
// Parent ID
if ((flags & CompressedFlags.HasParent) != 0)
{
prim.ParentID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
(block.Data[i++] << 16) + (block.Data[i++] << 24));
}
else
{
prim.ParentID = 0;
}
// Tree data
if ((flags & CompressedFlags.Tree) != 0)
{
prim.TreeSpecies = (Tree)block.Data[i++];
//prim.ScratchPad = Utils.EmptyBytes;
}
// Scratch pad
else if ((flags & CompressedFlags.ScratchPad) != 0)
{
prim.TreeSpecies = (Tree)0;
int size = block.Data[i++];
//prim.ScratchPad = new byte[size];
//Buffer.BlockCopy(block.Data, i, prim.ScratchPad, 0, size);
i += size;
}
prim.ScratchPad = Utils.EmptyBytes;
// Floating text
if ((flags & CompressedFlags.HasText) != 0)
{
int idx = i;
while (block.Data[i] != 0)
{
i++;
}
// Floating text
prim.Text = Utils.BytesToString(block.Data, idx, i - idx);
i++;
// Text color
prim.TextColor = new Color4(block.Data, i,false,true);
i += 4;
}
else
{
prim.Text = String.Empty;
}
// Media URL
if ((flags & CompressedFlags.MediaURL) != 0)
{
int idx = i;
while (block.Data[i] != 0)
{
i++;
}
prim.MediaURL = Utils.BytesToString(block.Data, idx, i - idx);
i++;
}
// Particle system
if ((flags & CompressedFlags.HasParticles) != 0)
{
prim.ParticleSys = new Primitive.ParticleSystem(block.Data, i);
i += 86;
}
// Extra parameters
i += prim.SetExtraParamsFromBytes(block.Data, i);
//Sound data
if ((flags & CompressedFlags.HasSound) != 0)
{
prim.Sound = new UUID(block.Data, i);
i += 16;
prim.SoundGain = Utils.BytesToFloat(block.Data, i);
i += 4;
prim.SoundFlags = (SoundFlags)block.Data[i++];
prim.SoundRadius = Utils.BytesToFloat(block.Data, i);
i += 4;
}
// Name values
if ((flags & CompressedFlags.HasNameValues) != 0)
{
string text = String.Empty;
while (block.Data[i] != 0)
{
text += (char)block.Data[i];
i++;
}
i++;
// Parse the name values
if (text.Length > 0)
{
string[] lines = text.Split('\n');
prim.NameValues = new NameValue[lines.Length];
for (int j = 0; j < lines.Length; j++)
{
if (!String.IsNullOrEmpty(lines[j]))
{
NameValue nv = new NameValue(lines[j]);
prim.NameValues[j] = nv;
}
}
}
}
prim.PrimData.PathCurve = (PathCurve)block.Data[i++];
ushort pathBegin = Utils.BytesToUInt16(block.Data, i); i += 2;
prim.PrimData.PathBegin = Primitive.UnpackBeginCut(pathBegin);
ushort pathEnd = Utils.BytesToUInt16(block.Data, i); i += 2;
prim.PrimData.PathEnd = Primitive.UnpackEndCut(pathEnd);
prim.PrimData.PathScaleX = Primitive.UnpackPathScale(block.Data[i++]);
prim.PrimData.PathScaleY = Primitive.UnpackPathScale(block.Data[i++]);
prim.PrimData.PathShearX = Primitive.UnpackPathShear((sbyte)block.Data[i++]);
prim.PrimData.PathShearY = Primitive.UnpackPathShear((sbyte)block.Data[i++]);
prim.PrimData.PathTwist = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
prim.PrimData.PathTwistBegin = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
prim.PrimData.PathRadiusOffset = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
prim.PrimData.PathTaperX = Primitive.UnpackPathTaper((sbyte)block.Data[i++]);
prim.PrimData.PathTaperY = Primitive.UnpackPathTaper((sbyte)block.Data[i++]);
prim.PrimData.PathRevolutions = Primitive.UnpackPathRevolutions(block.Data[i++]);
prim.PrimData.PathSkew = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
prim.PrimData.profileCurve = block.Data[i++];
ushort profileBegin = Utils.BytesToUInt16(block.Data, i); i += 2;
prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut(profileBegin);
ushort profileEnd = Utils.BytesToUInt16(block.Data, i); i += 2;
prim.PrimData.ProfileEnd = Primitive.UnpackEndCut(profileEnd);
ushort profileHollow = Utils.BytesToUInt16(block.Data, i); i += 2;
prim.PrimData.ProfileHollow = Primitive.UnpackProfileHollow(profileHollow);
// TextureEntry
int textureEntryLength = (int)Utils.BytesToUInt(block.Data, i);
i += 4;
prim.Textures = new Primitive.TextureEntry(block.Data, i, textureEntryLength);
i += textureEntryLength;
// Texture animation
if ((flags & CompressedFlags.TextureAnimation) != 0)
{
//int textureAnimLength = (int)Utils.BytesToUIntBig(block.Data, i);
i += 4;
prim.TextureAnim = new Primitive.TextureAnimation(block.Data, i);
}
#endregion
prim.IsAttachment = (flags & CompressedFlags.HasNameValues) != 0 && prim.ParentID != 0;
#region Raise Events
EventHandler<PrimEventArgs> handler = m_ObjectUpdate;
if (handler != null)
handler(this, new PrimEventArgs(simulator, prim, update.RegionData.TimeDilation, isNew, prim.IsAttachment));
#endregion
}
catch (IndexOutOfRangeException ex)
{
Logger.Log("Error decoding an ObjectUpdateCompressed packet", Helpers.LogLevel.Warning, Client, ex);
Logger.Log(block, Helpers.LogLevel.Warning);
}
}
}