From d44b50ee462978b4899c0b142f6ecbfb553f06b6 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 15 Oct 2009 15:25:02 -0700 Subject: * Removed some of the redundant broadcast functions in Scene and SceneGraph so it is clear who/what the broadcast is going to each time * Removed two redundant parameters from SceneObjectPart * Changed some code in terse update sending that was meant to work with references to work with value types (since Vector3 and Quaternion are structs) * Committing a preview of a new method for sending object updates efficiently (all commented out for now) --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 229 ++++++++++++++++++++- 1 file changed, 228 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 8487adc..82a2cdd 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -51,6 +51,44 @@ using Nini.Config; namespace OpenSim.Region.ClientStack.LindenUDP { + #region Enums + + /// + /// Specifies the fields that have been changed when sending a prim or + /// avatar update + /// + [Flags] + public enum PrimUpdateFlags : uint + { + None = 0, + AttachmentPoint = 1 << 0, + Material = 1 << 1, + ClickAction = 1 << 2, + Scale = 1 << 3, + ParentID = 1 << 4, + PrimFlags = 1 << 5, + PrimData = 1 << 6, + MediaURL = 1 << 7, + ScratchPad = 1 << 8, + Textures = 1 << 9, + TextureAnim = 1 << 10, + NameValue = 1 << 11, + Position = 1 << 12, + Rotation = 1 << 13, + Velocity = 1 << 14, + Acceleration = 1 << 15, + AngularVelocity = 1 << 16, + CollisionPlane = 1 << 17, + Text = 1 << 18, + Particles = 1 << 19, + ExtraData = 1 << 20, + Sound = 1 << 21, + Joint = 1 << 22, + FullUpdate = UInt32.MaxValue + } + + #endregion Enums + public delegate bool PacketMethod(IClientAPI simClient, Packet packet); /// @@ -3159,6 +3197,195 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion + #region Prim/Avatar Updates + + /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags) + { + bool canUseCompressed, canUseImproved; + UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved); + + if (!canUseImproved && !canUseCompressed) + SendFullObjectUpdate(obj, creatorFlags, updateFlags); + else if (!canUseImproved) + SendObjectUpdateCompressed(obj, creatorFlags, updateFlags); + else + SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags); + } + + void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags) + { + IClientAPI owner; + if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView) + { + LLClientView llOwner = (LLClientView)owner; + + // Send an update out to the owner + ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket(); + updateToOwner.RegionData.RegionHandle = obj.RegionHandle; + //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue); + updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0); + + m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true); + } + + // Send an update out to everyone else + ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket(); + updateToOthers.RegionData.RegionHandle = obj.RegionHandle; + //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue); + updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0); + + m_scene.ClientManager.ForEach( + delegate(IClientAPI client) + { + if (client.AgentId != obj.OwnerID && client is LLClientView) + { + LLClientView llClient = (LLClientView)client; + m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true); + } + } + ); + } + + void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags) + { + } + + void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags) + { + } + + void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved) + { + canUseCompressed = true; + canUseImproved = true; + + if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None) + { + canUseCompressed = false; + canUseImproved = false; + } + else + { + if ((updateFlags & PrimUpdateFlags.Velocity) != 0 || + (updateFlags & PrimUpdateFlags.Acceleration) != 0 || + (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 || + (updateFlags & PrimUpdateFlags.Joint) != 0) + { + canUseCompressed = false; + } + + if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 || + (updateFlags & PrimUpdateFlags.ParentID) != 0 || + (updateFlags & PrimUpdateFlags.Scale) != 0 || + (updateFlags & PrimUpdateFlags.PrimData) != 0 || + (updateFlags & PrimUpdateFlags.Text) != 0 || + (updateFlags & PrimUpdateFlags.NameValue) != 0 || + (updateFlags & PrimUpdateFlags.ExtraData) != 0 || + (updateFlags & PrimUpdateFlags.TextureAnim) != 0 || + (updateFlags & PrimUpdateFlags.Sound) != 0 || + (updateFlags & PrimUpdateFlags.Particles) != 0 || + (updateFlags & PrimUpdateFlags.Material) != 0 || + (updateFlags & PrimUpdateFlags.ClickAction) != 0 || + (updateFlags & PrimUpdateFlags.MediaURL) != 0 || + (updateFlags & PrimUpdateFlags.Joint) != 0) + { + canUseImproved = false; + } + } + } + + static ObjectUpdatePacket.ObjectDataBlock BuildUpdateBlockFromPrim(SceneObjectPart prim, UUID assetID, PrimFlags flags, uint crc) + { + byte[] objectData = new byte[60]; + prim.OffsetPosition.ToBytes(objectData, 0); + prim.Velocity.ToBytes(objectData, 12); + prim.Acceleration.ToBytes(objectData, 24); + prim.RotationOffset.ToBytes(objectData, 36); + prim.AngularVelocity.ToBytes(objectData, 48); + + ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); + update.ClickAction = (byte)prim.ClickAction; + update.CRC = crc; + update.ExtraParams = prim.Shape.ExtraParams ?? Utils.EmptyBytes; + update.Flags = (byte)flags; + update.FullID = prim.UUID; + update.ID = prim.LocalId; + //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated + //update.JointPivot = Vector3.Zero; + //update.JointType = 0; + update.Material = prim.Material; + update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim + if (prim.IsAttachment) + update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + assetID); + else + update.NameValue = Utils.EmptyBytes; + update.ObjectData = objectData; + update.ParentID = prim.ParentID; + update.PathBegin = prim.Shape.PathBegin; + update.PathCurve = prim.Shape.PathCurve; + update.PathEnd = prim.Shape.PathEnd; + update.PathRadiusOffset = prim.Shape.PathRadiusOffset; + update.PathRevolutions = prim.Shape.PathRevolutions; + update.PathScaleX = prim.Shape.PathScaleX; + update.PathScaleY = prim.Shape.PathScaleY; + update.PathShearX = prim.Shape.PathShearX; + update.PathShearY = prim.Shape.PathShearY; + update.PathSkew = prim.Shape.PathSkew; + update.PathTaperX = prim.Shape.PathTaperX; + update.PathTaperY = prim.Shape.PathTaperY; + update.PathTwist = prim.Shape.PathTwist; + update.PathTwistBegin = prim.Shape.PathTwistBegin; + update.PCode = prim.Shape.PCode; + update.ProfileBegin = prim.Shape.ProfileBegin; + update.ProfileCurve = prim.Shape.ProfileCurve; + update.ProfileEnd = prim.Shape.ProfileEnd; + update.ProfileHollow = prim.Shape.ProfileHollow; + update.PSBlock = prim.ParticleSystem ?? Utils.EmptyBytes; + update.TextColor = new Color4(prim.Color).GetBytes(true); + update.TextureAnim = prim.TextureAnimation ?? Utils.EmptyBytes; + update.TextureEntry = prim.Shape.TextureEntry ?? Utils.EmptyBytes; + update.Scale = prim.Scale; + update.State = prim.Shape.State; + update.Text = Util.StringToBytes256(prim.Text); + update.UpdateFlags = (uint)flags; + + if (prim.Sound != UUID.Zero) + { + update.Sound = prim.Sound; + update.OwnerID = prim.OwnerID; + update.Gain = (float)prim.SoundGain; + update.Radius = (float)prim.SoundRadius; + } + + switch ((PCode)prim.Shape.PCode) + { + case PCode.Grass: + case PCode.Tree: + case PCode.NewTree: + update.Data = new byte[] { prim.Shape.State }; + break; + default: + // TODO: Support ScratchPad + //if (prim.ScratchPad != null) + //{ + // update.Data = new byte[prim.ScratchPad.Length]; + // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length); + //} + //else + //{ + // update.Data = Utils.EmptyBytes; + //} + update.Data = Utils.EmptyBytes; + break; + } + + return update; + }*/ + + #endregion Prim/Avatar Updates + #region Avatar Packet/data sending Methods /// @@ -3365,7 +3592,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) return; - + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) rotation = Quaternion.Identity; -- cgit v1.1