diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5b51e485ca..0bb25480ab 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -980,7 +980,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP 0xff, 0xff, 0, 250 // ID 250 (low frequency bigendian) }; - public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) + public unsafe void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) { // reset agent update args m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue; @@ -988,39 +988,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_thisAgentUpdateArgs.ControlFlags = 0; UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - byte[] data = buf.Data; + byte[] bdata = buf.Data; //setup header - Buffer.BlockCopy(AgentMovementCompleteHeader, 0, data, 0, 10); + Buffer.BlockCopy(AgentMovementCompleteHeader, 0, bdata, 0, 10); - //AgentData block - m_agentId.ToBytes(data, 10); // 26 - m_sessionId.ToBytes(data, 26); // 42 + fixed(byte* data = bdata) + { + //AgentData block + m_agentId.ToBytes(data + 10); // 26 + m_sessionId.ToBytes(data + 26); // 42 - //Data block - if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) - m_startpos.ToBytes(data, 42); //54 - else - pos.ToBytes(data, 42); //54 - look.ToBytes(data, 54); // 66 - Utils.UInt64ToBytesSafepos(regInfo.RegionHandle, data, 66); // 74 - Utils.UIntToBytesSafepos((uint)Util.UnixTimeSinceEpoch(), data, 74); //78 + //Data block + if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) + m_startpos.ToBytes(data + 42); //54 + else + pos.ToBytes(data + 42); //54 + look.ToBytes(data + 54); // 66 + //Utils.UInt64ToBytesSafepos(regInfo.RegionHandle, data + 66); // 74 + //Utils.UIntToBytesSafepos((uint)Util.UnixTimeSinceEpoch(), data + 74); //78 + Utils.UInt64ToBytes(regInfo.RegionHandle, data + 66); // 74 + Utils.IntToBytes((int)Util.UnixTimeSinceEpoch(), data + 74); //78 - //SimData - int len = m_regionChannelVersion.Length; - if(len == 0) - { - data[78] = 0; - data[79] = 0; + //SimData + int len = m_regionChannelVersion.Length; + if(len == 0) + { + data[78] = 0; + data[79] = 0; + } + else + { + data[78] = (byte)len; + data[79] = (byte)(len >> 8); + Buffer.BlockCopy(m_regionChannelVersion, 0, bdata, 80, len); + } + buf.DataLength = 80 + len; } - else - { - data[78] = (byte)len; - data[79] = (byte)(len >> 8); - Buffer.BlockCopy(m_regionChannelVersion, 0, data, 80, len); - } - - buf.DataLength = 80 + len; m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown); } @@ -4577,7 +4581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); } - public void SendEntityTerseUpdateImmediate(ISceneEntity ent) + public unsafe void SendEntityTerseUpdateImmediate(ISceneEntity ent) { if (ent == null) return; @@ -4585,24 +4589,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); //setup header and regioninfo block - Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7); - - Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15); - buf.Data[17] = 1; - int pos = 18; + fixed(byte* bdata = &buf.Data[0]) + { + Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), bdata + 15); + bdata[17] = 1; + byte* data = bdata + 18; - if (ent is ScenePresence) - { - Utils.UInt64ToBytesSafepos(((ScenePresence)ent).RegionHandle, buf.Data, 7); - CreateAvatartImprovedTerseBlock((ScenePresence)ent, buf.Data, ref pos); + if (ent is ScenePresence) + { + Utils.UInt64ToBytes(((ScenePresence)ent).RegionHandle, bdata + 7); + CreateAvatartImprovedTerseBlock((ScenePresence)ent, ref data); + } + else + { + Utils.UInt64ToBytes(m_scene.RegionInfo.RegionHandle, bdata + 7); + CreatePartImprovedTerseBlock((SceneObjectPart)ent, ref data, false); + } + buf.DataLength = (int)(data - bdata); } - else - { - Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); - CreatePartImprovedTerseBlock((SceneObjectPart)ent, buf.Data, ref pos, false); - } - buf.DataLength = pos; m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true); } @@ -6725,14 +6730,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Helper Methods private void ClampVectorForUint(ref Vector3 v, float max) { - float a,b; + float a, b; a = Math.Abs(v.X); b = Math.Abs(v.Y); - if(b > a) + if (b > a) a = b; - b= Math.Abs(v.Z); - if(b > a) + b = Math.Abs(v.Z); + if (b > a) a = b; if (a > max) @@ -6847,6 +6852,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2; // Rotation + Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2; Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2; Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2; @@ -6888,7 +6894,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UIntToBytesSafepos(part.LocalId, data, pos); pos += 4; - if(part.ParentGroup.AttachmentPoint == 0) + if (part.ParentGroup.AttachmentPoint == 0) data[pos++] = 0; else { @@ -6903,34 +6909,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP part.RelativePosition.ToBytes(data, pos); pos += 12; - // Velocity - Vector3 vtmp = part.Velocity; - ClampVectorForUint(ref vtmp, 128f); - Utils.FloatToUInt16Bytes(vtmp.X, 128.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Y, 128.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Z, 128.0f, data, pos); pos += 2; + part.Velocity.ClampedToShortsBytes(128f, data, pos); pos += 6; // Acceleration - vtmp = part.Acceleration; - ClampVectorForUint(ref vtmp, 64f); - Utils.FloatToUInt16Bytes(vtmp.X, 64.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Y, 64.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Z, 64.0f, data, pos); pos += 2; + part.Acceleration.ClampedToShortsBytes(64f, data, pos); pos += 6; // Rotation - Quaternion rotation = part.RotationOffset; - Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2; + part.RotationOffset.ToShortsBytes(data, pos); pos += 8; // Angular Velocity - vtmp = part.AngularVelocity; - ClampVectorForUint(ref vtmp, 64f); - Utils.FloatToUInt16Bytes(vtmp.X, 64.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Y, 64.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Z, 64.0f, data, pos); pos += 2; + part.AngularVelocity.ClampedToShortsBytes(64f, data, pos); pos += 6; // texture entry block size if (includeTexture && part.Shape.TextureEntry != null) @@ -6955,6 +6944,66 @@ namespace OpenSim.Region.ClientStack.LindenUDP // total size 47 + (texture size + 4) } + protected unsafe void CreatePartImprovedTerseBlock(SceneObjectPart part, ref byte* data, bool includeTexture) + { + //object block size + *data++ = 44; + + // LocalID + Utils.UIntToBytes(part.LocalId, data); + data += 4; + + if (part.ParentGroup.AttachmentPoint == 0) + *data++ = 0; + else + { + uint attachPoint = 0xff & part.ParentGroup.AttachmentPoint; + *data++ = (byte)(attachPoint << 4 | attachPoint >> 4); + } + + // no Avatar/CollisionPlane + *data++ = 0; + + // Position + part.RelativePosition.ToBytes(data); + data += 12; + + // Velocity + part.Velocity.ClampedToShortsBytes(128f, data); data += 6; + + // Acceleration + part.Acceleration.ClampedToShortsBytes(64f, data); data += 6; + + // Rotation + part.RotationOffset.ToShortsBytes(data); data += 8; + + // Angular Velocity + part.AngularVelocity.ClampedToShortsBytes(64f, data); data += 6; + + // texture entry block size + if (includeTexture && part.Shape.TextureEntry != null) + { + byte[] te = part.Shape.TextureEntry; + int len = te.Length & 0x7fff; + int totlen = len + 4; + *data++ = (byte)totlen; + *data++ = (byte)(totlen >> 8); + *data++ = (byte)len; // wtf ??? + *data++ = (byte)(len >> 8); + *data++ = 0; + *data++ = 0; + fixed(byte* t = &te[0]) + Buffer.MemoryCopy(t, data, 4096, (long)len); + data += len; + } + else + { + *data++ = 0; + *data++ = 0; + } + // total size 47 + (texture size + 4) + } + protected void CreateAvatartImprovedTerseBlock(ScenePresence presence, byte[] data, ref int pos) { //m_log.DebugFormat( @@ -6971,13 +7020,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Avatar/CollisionPlane data[pos++] = 1; - Vector4 collisionPlane = presence.CollisionPlane; //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane); - if (collisionPlane == Vector4.Zero) + if (presence.CollisionPlane.IsZero()) Vector4.UnitW.ToBytes(data, pos); else - collisionPlane.ToBytes(data, pos); + presence.CollisionPlane.ToBytes(data, pos); pos += 16; // Position @@ -6985,11 +7033,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP pos += 12; // Velocity - Vector3 vtmp = presence.Velocity; - ClampVectorForUint(ref vtmp, 128f); - Utils.FloatToUInt16Bytes(vtmp.X, 128.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Y, 128.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Z, 128.0f, data, pos); pos += 2; + presence.Velocity.ClampedToShortsBytes(128f, data, pos); pos += 6; // Acceleration is zero Utils.UIntToBytesSafepos(0x7fff7fff, data, pos); pos += 4; @@ -7004,7 +7048,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP float rz = rotation.Z; float rw = rotation.W; float a = rz * rz + rw * rw; - if(a > -1e-6f && a < 1e-6f) + if (a > -1e-6f && a < 1e-6f) { Utils.UIntToBytesSafepos(0xffff7fff, data, pos); pos += 4; } @@ -7017,18 +7061,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2; + rotation.ToShortsBytes(data, pos); pos += 8; } // Angular Velocity - vtmp = presence.AngularVelocity; - ClampVectorForUint(ref vtmp, 64f); - Utils.FloatToUInt16Bytes(vtmp.X, 64.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Y, 64.0f, data, pos); pos += 2; - Utils.FloatToUInt16Bytes(vtmp.Z, 64.0f, data, pos); pos += 2; + presence.AngularVelocity.ClampedToShortsBytes(64f, data, pos); pos += 6; //texture data[pos++] = 0; @@ -7036,6 +7073,73 @@ namespace OpenSim.Region.ClientStack.LindenUDP // total size 63 } + protected unsafe void CreateAvatartImprovedTerseBlock(ScenePresence presence, ref byte* data) + { + //m_log.DebugFormat( + // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); + + //object block size + *data++ = 60; + // LocalID + Utils.UIntToBytes(presence.LocalId, data); + data += 4; + + *data++ = presence.State; + + // Avatar/CollisionPlane + *data++ = 1; + //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane); + if (presence.CollisionPlane.IsZero()) + Vector4.UnitW.ToBytes(data); + else + presence.CollisionPlane.ToBytes(data); + data += 16; + + // Position + presence.OffsetPosition.ToBytes(data); + data += 12; + + // Velocity + presence.Velocity.ClampedToShortsBytes(128f, data); data += 6; + + // Acceleration is zero + Utils.UIntToBytes(0x7fff7fff, data); data += 4; + Utils.UInt16ToBytes(0x7fff, data); data += 2; + + // Rotation + // tpvs can only see rotations around Z in some cases + Quaternion rotation = presence.Rotation; + if (!presence.Flying && !presence.IsSatOnObject) + { + Utils.UIntToBytes(0x7fff7fff, data); data += 4; + float rz = rotation.Z; + float rw = rotation.W; + float a = rz * rz + rw * rw; + if (a > -1e-6f && a < 1e-6f) + { + Utils.UIntToBytes(0xffff7fff, data); data += 4; + } + else + { + a = 1.0f / (float)Math.Sqrt(a); + Utils.FloatToUInt16Bytes(rz * a, 1.0f, data); data += 2; + Utils.FloatToUInt16Bytes(rw * a, 1.0f, data); data += 2; + } + } + else + { + rotation.ToShortsBytes(data); data += 8; + } + + // Angular Velocity + presence.AngularVelocity.ClampedToShortsBytes(64f, data); data += 6; + + //texture + *data++ = 0; + *data++ = 0; + // total size 63 + } + protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos) { Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;