protected void ImprovedTerseObjectUpdateHandler(object sender, PacketReceivedEventArgs e)
{
Packet packet = e.Packet;
Simulator simulator = e.Simulator;
ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)packet;
UpdateDilation(simulator, terse.RegionData.TimeDilation);
for (int i = 0; i < terse.ObjectData.Length; i++)
{
ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = terse.ObjectData[i];
try
{
int pos = 4;
uint localid = Utils.BytesToUInt(block.Data, 0);
// Check if we are interested in this update
if (!Client.Settings.ALWAYS_DECODE_OBJECTS
&& localid != Client.Self.localID
&& m_TerseObjectUpdate == null)
{
continue;
}
#region Decode update data
ObjectMovementUpdate update = new ObjectMovementUpdate();
// LocalID
update.LocalID = localid;
// State
update.State = block.Data[pos++];
// Avatar boolean
update.Avatar = (block.Data[pos++] != 0);
// Collision normal for avatar
if (update.Avatar)
{
update.CollisionPlane = new Vector4(block.Data, pos);
pos += 16;
}
// Position
update.Position = new Vector3(block.Data, pos);
pos += 12;
// Velocity
update.Velocity = new Vector3(
Utils.UInt16ToFloat(block.Data, pos, -128.0f, 128.0f),
Utils.UInt16ToFloat(block.Data, pos + 2, -128.0f, 128.0f),
Utils.UInt16ToFloat(block.Data, pos + 4, -128.0f, 128.0f));
pos += 6;
// Acceleration
update.Acceleration = new Vector3(
Utils.UInt16ToFloat(block.Data, pos, -64.0f, 64.0f),
Utils.UInt16ToFloat(block.Data, pos + 2, -64.0f, 64.0f),
Utils.UInt16ToFloat(block.Data, pos + 4, -64.0f, 64.0f));
pos += 6;
// Rotation (theta)
update.Rotation = new Quaternion(
Utils.UInt16ToFloat(block.Data, pos, -1.0f, 1.0f),
Utils.UInt16ToFloat(block.Data, pos + 2, -1.0f, 1.0f),
Utils.UInt16ToFloat(block.Data, pos + 4, -1.0f, 1.0f),
Utils.UInt16ToFloat(block.Data, pos + 6, -1.0f, 1.0f));
pos += 8;
// Angular velocity (omega)
update.AngularVelocity = new Vector3(
Utils.UInt16ToFloat(block.Data, pos, -64.0f, 64.0f),
Utils.UInt16ToFloat(block.Data, pos + 2, -64.0f, 64.0f),
Utils.UInt16ToFloat(block.Data, pos + 4, -64.0f, 64.0f));
pos += 6;
// Textures
// FIXME: Why are we ignoring the first four bytes here?
if (block.TextureEntry.Length != 0)
update.Textures = new Primitive.TextureEntry(block.TextureEntry, 4, block.TextureEntry.Length - 4);
#endregion Decode update data
Primitive obj = !Client.Settings.OBJECT_TRACKING ? null : (update.Avatar) ?
(Primitive)GetAvatar(simulator, update.LocalID, UUID.Zero) :
(Primitive)GetPrimitive(simulator, update.LocalID, UUID.Zero);
// Fire the pre-emptive notice (before we stomp the object)
EventHandler<TerseObjectUpdateEventArgs> handler = m_TerseObjectUpdate;
if (handler != null)
{
WorkPool.QueueUserWorkItem(delegate(object o)
{ handler(this, new TerseObjectUpdateEventArgs(simulator, obj, update, terse.RegionData.TimeDilation)); });
}
#region Update Client.Self
if (update.LocalID == Client.Self.localID)
{
Client.Self.collisionPlane = update.CollisionPlane;
Client.Self.relativePosition = update.Position;
Client.Self.velocity = update.Velocity;
Client.Self.acceleration = update.Acceleration;
Client.Self.relativeRotation = update.Rotation;
Client.Self.angularVelocity = update.AngularVelocity;
}
#endregion Update Client.Self
if (Client.Settings.OBJECT_TRACKING && obj != null)
{
obj.Position = update.Position;
obj.Rotation = update.Rotation;
obj.Velocity = update.Velocity;
obj.CollisionPlane = update.CollisionPlane;
obj.Acceleration = update.Acceleration;
obj.AngularVelocity = update.AngularVelocity;
obj.PrimData.State = update.State;
if (update.Textures != null)
obj.Textures = update.Textures;
}
}
catch (Exception ex)
{
Logger.Log(ex.Message, Helpers.LogLevel.Warning, Client, ex);
}
}
}