diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f8ff3c4ec6..dd06e402c8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3894,22 +3894,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (ent is ScenePresence) { ScenePresence presence = ent as ScenePresence; - UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); - //setup header and regioninfo block Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7); - Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); - Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15); - buf.Data[17] = 1; - int pos = 18; - CreateAvatarUpdateBlock(presence, buf.Data, ref pos); - - buf.DataLength = pos; - m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true); + LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); + zc.Position = 7; + zc.AddUInt64(m_scene.RegionInfo.RegionHandle); + zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); + zc.AddByte(1); // block count + CreateAvatarUpdateBlock(presence, zc); + buf.DataLength = zc.Finish(); + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, false); } - else if(ent is SceneObjectPart) { ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); @@ -5985,6 +5982,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP Array.Clear(dest, pos, lastzeros); pos += lastzeros; } + protected void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc) + { + Quaternion rotation = data.Rotation; + // tpvs can only see rotations around Z in some cases + if (!data.Flying && !data.IsSatOnObject) + { + rotation.X = 0f; + rotation.Y = 0f; + } + rotation.Normalize(); + + zc.AddUInt(data.LocalId); + zc.AddByte(0); + zc.AddUUID(data.UUID); + zc.AddZeros(4); // crc unused + zc.AddByte((byte)PCode.Avatar); + zc.AddByte((byte)Material.Flesh); + zc.AddByte(0); // clickaction + zc.AddVector3(data.Appearance.AvatarSize); + + // objectdata block + zc.AddByte(76); // fixed avatar block size + zc.AddVector4(data.CollisionPlane); + zc.AddVector3(data.OffsetPosition); + zc.AddVector3(data.Velocity); + //zc.AddVector3(acceleration); + zc.AddZeros(12); + zc.AddNormQuat(rotation); + //zc.AddVector3(angularvelocity); + zc.AddZeros(12); + + SceneObjectPart parentPart = data.ParentPart; + if (parentPart != null) + zc.AddUInt(parentPart.ParentGroup.LocalId); + else + zc.AddZeros(4); + + zc.AddZeros(4); //update flags + + //pbs + zc.AddByte(16); + zc.AddByte(1); + //Utils.UInt16ToBytes(0, dest, pos); pos += 2; + //Utils.UInt16ToBytes(0, dest, pos); pos += 2; + zc.AddZeros(4); + + zc.AddByte(100); + zc.AddByte(100); + + // rest of pbs is 0 (15), texture entry (2) and texture anim (1) + const int pbszeros = 15 + 2 + 1; + zc.AddZeros(pbszeros); + + //NameValue + byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + + data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); + int len = nv.Length; + zc.AddByte((byte)len); + zc.AddByte((byte)(len >> 8)); + zc.AddBytes(nv, len); + + // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1), + // sound id(16), sound owner(16) gain (4), flags (1), radius (4) + // jointtype(1) joint pivot(12) joint offset(12) + const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12; + zc.AddZeros(lastzeros); + } + + // protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) { @@ -6008,32 +6074,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //update.JointPivot = Vector3.Zero; //update.JointType = 0; update.Material = part.Material; -/* - if (data.ParentGroup.IsAttachment) - { - update.NameValue - = Util.StringToBytes256( - string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID)); - - update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); - -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}", -// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name); -// -// m_log.DebugFormat( -// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", -// update.State, data.Name, data.LocalId, Name); - } - else - { - update.NameValue = Utils.EmptyBytes; - - // The root part state is the canonical state for all parts of the object. The other part states in the - // case for attachments may contain conflicting values that can end up crashing the viewer. - update.State = data.ParentGroup.RootPart.Shape.State; - } -*/ if (part.ParentGroup.IsAttachment) { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs new file mode 100644 index 0000000000..4841adafd2 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs @@ -0,0 +1,279 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Framework; +using Nini.Config; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class LLUDPZeroEncoder + { + private byte[] m_tmp = new byte[16]; + private byte[] m_dest; + private int zerocount; + private int pos; + + public LLUDPZeroEncoder() + { + } + + public LLUDPZeroEncoder(byte[] data) + { + m_dest = data; + zerocount = 0; + } + + public byte[] Data + { + get + { + return m_dest; + } + set + { + m_dest = value; + } + } + + public int ZeroCount + { + get + { + return zerocount; + } + set + { + zerocount = value; + } + } + + public int Position + { + get + { + return pos; + } + set + { + pos = value; + } + } + + public unsafe void AddZeros(int len) + { + zerocount += len; + while (zerocount > 255) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = 0xff; + zerocount -= 256; + } + } + + public unsafe int Finish() + { + if(zerocount > 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = (byte)zerocount; + } + return pos; + } + + public unsafe void AddBytes(byte[] src, int srclen) + { + for (int i = 0; i < srclen; ++i) + { + if (src[i] == 0x00) + { + zerocount++; + if (zerocount == 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = 0xff; + zerocount++; + } + } + else + { + if (zerocount != 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = (byte)zerocount; + zerocount = 0; + } + + m_dest[pos++] = src[i]; + } + } + } + + public void AddByte(byte v) + { + if (v == 0x00) + { + zerocount++; + if (zerocount == 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = 0xff; + zerocount++; + } + } + else + { + if (zerocount != 0) + { + m_dest[pos++] = 0x00; + m_dest[pos++] = (byte)zerocount; + zerocount = 0; + } + + m_dest[pos++] = v; + } + } + + public void AddInt16(short v) + { + if (v == 0) + AddZeros(2); + else + { + Utils.Int16ToBytes(v, m_tmp, 0); + AddBytes(m_tmp, 2); + } + } + + public void AddUInt16(ushort v) + { + if (v == 0) + AddZeros(2); + else + { + Utils.UInt16ToBytes(v, m_tmp, 0); + AddBytes(m_tmp, 2); + } + } + + public void AddInt(int v) + { + if (v == 0) + AddZeros(4); + else + { + Utils.IntToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 4); + } + } + + public unsafe void AddUInt(uint v) + { + if (v == 0) + AddZeros(4); + else + { + Utils.UIntToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 4); + } + } + + public void AddFloatToUInt16(float v, float range) + { + Utils.FloatToUInt16Bytes(v, range, m_tmp, 0); + AddBytes(m_tmp, 2); + } + + public void AddFloat(float v) + { + if (v == 0f) + AddZeros(4); + else + { + Utils.FloatToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 4); + } + } + + public void AddInt64(long v) + { + if (v == 0) + AddZeros(8); + else + { + Utils.Int64ToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 8); + } + } + + public void AddUInt64(ulong v) + { + if (v == 0) + AddZeros(8); + else + { + Utils.UInt64ToBytesSafepos(v, m_tmp, 0); + AddBytes(m_tmp, 8); + } + } + + public void AddVector3(Vector3 v) + { + if (v == Vector3.Zero) + AddZeros(12); + else + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 12); + } + } + + public void AddVector4(Vector4 v) + { + if (v == Vector4.Zero) + AddZeros(16); + else + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 16); + } + } + + public void AddNormQuat(Quaternion v) + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 12); + } + + public void AddUUID(UUID v) + { + v.ToBytes(m_tmp, 0); + AddBytes(m_tmp, 16); + } + } +}