From 3ced78e8ff23d8d9fbf28a01231f7737643a1c54 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Sun, 12 Nov 2006 11:33:42 +0000 Subject: [PATCH] CopyBot: * More aggressive AgentUpdate timer * Workaround hack for prims appearing in the wrong position for other clients * Fixed ViewerEffect handling to copy over multiple Effect blocks, and never send ViewerEffect packets with no blocks (which will crash the sim) * CopyBot will rotate to face the original avatar (kind of, needs refining) libsecondlife: * Added an enum for AttachmentPoint * Couple additional sanity checks for null simulators after disconnecting * Can build a quaternion from normalized X/Y/Z only now git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@569 52acb1d6-8a22-11de-b505-999d5b087335 --- libsecondlife-cs/NetworkManager.cs | 9 +- libsecondlife-cs/ObjectManager.cs | 256 ++++++++++++++++------------- libsecondlife-cs/Types.cs | 16 ++ 3 files changed, 169 insertions(+), 112 deletions(-) diff --git a/libsecondlife-cs/NetworkManager.cs b/libsecondlife-cs/NetworkManager.cs index 8ca3eef2..1cb7a617 100644 --- a/libsecondlife-cs/NetworkManager.cs +++ b/libsecondlife-cs/NetworkManager.cs @@ -722,7 +722,7 @@ namespace libsecondlife /// public void SendPacket(Packet packet, Simulator simulator) { - if (simulator.Connected) + if (simulator != null && simulator.Connected) { simulator.SendPacket(packet, true); } @@ -1282,6 +1282,13 @@ namespace libsecondlife private void DisconnectTimer_Elapsed(object sender, ElapsedEventArgs ev) { + if (CurrentSim == null) + { + DisconnectTimer.Stop(); + connected = false; + return; + } + // If the current simulator is disconnected, shutdown+callback+return if (CurrentSim.DisconnectCandidate) { diff --git a/libsecondlife-cs/ObjectManager.cs b/libsecondlife-cs/ObjectManager.cs index 559de154..0637a2d9 100644 --- a/libsecondlife-cs/ObjectManager.cs +++ b/libsecondlife-cs/ObjectManager.cs @@ -77,11 +77,11 @@ namespace libsecondlife public LLVector3 RotationVelocity; } - /// - /// Handles all network traffic related to prims and avatar positions and + /// + /// Handles all network traffic related to prims and avatar positions and /// movement. - /// - public class ObjectManager + /// + public class ObjectManager { /// /// @@ -90,7 +90,7 @@ namespace libsecondlife /// /// /// - public delegate void NewPrimCallback(Simulator simulator, PrimObject prim, ulong regionHandle, + public delegate void NewPrimCallback(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation); /// /// @@ -99,7 +99,7 @@ namespace libsecondlife /// /// /// - public delegate void NewAvatarCallback(Simulator simulator, Avatar avatar, ulong regionHandle, + public delegate void NewAvatarCallback(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation); /// /// @@ -108,7 +108,7 @@ namespace libsecondlife /// /// /// - public delegate void PrimMovedCallback(Simulator simulator, PrimUpdate prim, ulong regionHandle, + public delegate void PrimMovedCallback(Simulator simulator, PrimUpdate prim, ulong regionHandle, ushort timeDilation); /// /// @@ -117,7 +117,7 @@ namespace libsecondlife /// /// /// - public delegate void AvatarMovedCallback(Simulator simulator, AvatarUpdate avatar, ulong regionHandle, + public delegate void AvatarMovedCallback(Simulator simulator, AvatarUpdate avatar, ulong regionHandle, ushort timeDilation); /// /// @@ -167,6 +167,40 @@ namespace libsecondlife Transfer = 0x00002000 } + public enum AttachmentPoint + { + Chest = 1, + Skull, + LeftShoulder, + RightShoulder, + LeftHand, + RightHand, + LeftFoot, + RightFoot, + Spine, + Pelvis, + Mouth, + Chin, + LeftEar, + RightEar, + LeftEyeball, + RightEyeball, + Nose, + RightUpperArm, + RightForarm, + LeftUpperArm, + LeftForearm, + RightHip, + RightUpperLeg, + RightLowerLeg, + LeftHip, + LeftUpperLeg, + LeftLowerLeg, + Stomach, + LeftPec, + RightPec + } + /// /// This event will be raised for every ObjectUpdate block that /// contains a new prim. @@ -388,116 +422,116 @@ namespace libsecondlife foreach (ObjectUpdatePacket.ObjectDataBlock block in update.ObjectData) { - switch(block.PCode) - { - case (byte)PCode.Prim: - if (OnNewPrim != null) - { - // New prim spotted - PrimObject prim = new PrimObject(Client); - - prim.Position = new LLVector3(block.ObjectData, 0); - prim.Rotation = new LLQuaternion(block.ObjectData, 36, true); - - // TODO: Parse the rest of the ObjectData byte array fields - - prim.LocalID = block.ID; - prim.State = block.State; - prim.ID = block.FullID; - prim.ParentID = block.ParentID; - //block.OwnerID Sound-related - prim.Material = block.Material; - prim.PathCurve = block.PathCurve; - prim.ProfileCurve = block.ProfileCurve; - prim.PathBegin = PrimObject.PathBeginFloat(block.PathBegin); - prim.PathEnd = PrimObject.PathEndFloat(block.PathEnd); - prim.PathScaleX = PrimObject.PathScaleFloat(block.PathScaleX); - prim.PathScaleY = PrimObject.PathScaleFloat(block.PathScaleY); - prim.PathShearX = PrimObject.PathShearFloat(block.PathShearX); - prim.PathShearY = PrimObject.PathShearFloat(block.PathShearY); - prim.PathTwist = block.PathTwist; //PrimObject.PathTwistFloat(block.PathTwist); - prim.PathTwistBegin = block.PathTwistBegin; //PrimObject.PathTwistFloat(block.PathTwistBegin); - prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat(block.PathRadiusOffset); - prim.PathTaperX = PrimObject.PathTaperFloat(block.PathTaperX); - prim.PathTaperY = PrimObject.PathTaperFloat(block.PathTaperY); - prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.PathRevolutions); - prim.PathSkew = PrimObject.PathSkewFloat(block.PathSkew); - prim.ProfileBegin = PrimObject.ProfileBeginFloat(block.ProfileBegin); - prim.ProfileEnd = PrimObject.ProfileEndFloat(block.ProfileEnd); - prim.ProfileHollow = block.ProfileHollow; - prim.Name = Helpers.FieldToString(block.NameValue); - //block.Data ? - prim.Text = ASCIIEncoding.ASCII.GetString(block.Text); - //block.TextColor LLColor4U of the hovering text - //block.MediaURL Quicktime stream - prim.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); - prim.TextureAnim = new TextureAnimation(block.TextureAnim, 0); - //block.JointType ? - //block.JointPivot ? - //block.JointAxisOrAnchor ? - prim.ParticleSys = new ParticleSystem(block.PSBlock, 0); - prim.SetExtraParamsFromBytes(block.ExtraParams, 0); - prim.Scale = block.Scale; - //block.Flags ? - prim.Flags = (ObjectFlags)block.UpdateFlags; - //block.ClickAction ? - //block.Gain Sound-related - //block.Sound Sound-related - //block.Radius Sound-related - + switch (block.PCode) + { + case (byte)PCode.Prim: if (OnNewPrim != null) { - OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation); - } - } - break; - case (byte)PCode.Avatar: - if (OnNewAvatar != null) - { - Avatar avatar = new Avatar(); + // New prim spotted + PrimObject prim = new PrimObject(Client); - string FirstName = ""; - string LastName = ""; - string GroupName = ""; + prim.Position = new LLVector3(block.ObjectData, 0); + prim.Rotation = new LLQuaternion(block.ObjectData, 36, true); - //avatar.CollisionPlane = new LLQuaternion(block.ObjectData, 0); - avatar.Position = new LLVector3(block.ObjectData, 16); - avatar.Rotation = new LLQuaternion(block.ObjectData, 52, true); + // TODO: Parse the rest of the ObjectData byte array fields - // TODO: Parse the rest of the ObjectData byte array fields + prim.LocalID = block.ID; + prim.State = block.State; + prim.ID = block.FullID; + prim.ParentID = block.ParentID; + //block.OwnerID Sound-related + prim.Material = block.Material; + prim.PathCurve = block.PathCurve; + prim.ProfileCurve = block.ProfileCurve; + prim.PathBegin = PrimObject.PathBeginFloat(block.PathBegin); + prim.PathEnd = PrimObject.PathEndFloat(block.PathEnd); + prim.PathScaleX = PrimObject.PathScaleFloat(block.PathScaleX); + prim.PathScaleY = PrimObject.PathScaleFloat(block.PathScaleY); + prim.PathShearX = PrimObject.PathShearFloat(block.PathShearX); + prim.PathShearY = PrimObject.PathShearFloat(block.PathShearY); + prim.PathTwist = block.PathTwist; //PrimObject.PathTwistFloat(block.PathTwist); + prim.PathTwistBegin = block.PathTwistBegin; //PrimObject.PathTwistFloat(block.PathTwistBegin); + prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat(block.PathRadiusOffset); + prim.PathTaperX = PrimObject.PathTaperFloat(block.PathTaperX); + prim.PathTaperY = PrimObject.PathTaperFloat(block.PathTaperY); + prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.PathRevolutions); + prim.PathSkew = PrimObject.PathSkewFloat(block.PathSkew); + prim.ProfileBegin = PrimObject.ProfileBeginFloat(block.ProfileBegin); + prim.ProfileEnd = PrimObject.ProfileEndFloat(block.ProfileEnd); + prim.ProfileHollow = block.ProfileHollow; + prim.Name = Helpers.FieldToString(block.NameValue); + //block.Data ? + prim.Text = ASCIIEncoding.ASCII.GetString(block.Text); + //block.TextColor LLColor4U of the hovering text + //block.MediaURL Quicktime stream + prim.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); + prim.TextureAnim = new TextureAnimation(block.TextureAnim, 0); + //block.JointType ? + //block.JointPivot ? + //block.JointAxisOrAnchor ? + prim.ParticleSys = new ParticleSystem(block.PSBlock, 0); + prim.SetExtraParamsFromBytes(block.ExtraParams, 0); + prim.Scale = block.Scale; + //block.Flags ? + prim.Flags = (ObjectFlags)block.UpdateFlags; + //block.ClickAction ? + //block.Gain Sound-related + //block.Sound Sound-related + //block.Radius Sound-related - ParseAvName(Helpers.FieldToString(block.NameValue), ref FirstName, ref LastName, ref GroupName); - - avatar.ID = block.FullID; - avatar.LocalID = block.ID; - avatar.Name = FirstName + " " + LastName; - avatar.GroupName = GroupName; - avatar.Online = true; - avatar.CurrentRegion = simulator.Region; - - avatar.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); - - if (FirstName == Client.Self.FirstName && LastName == Client.Self.LastName) - { - // Update our avatar - Client.Self.LocalID = avatar.LocalID; - Client.Self.Position = avatar.Position; - Client.Self.Rotation = avatar.Rotation; - } - else - { - if (OnNewAvatar != null) + if (OnNewPrim != null) { - OnNewAvatar(simulator, avatar, update.RegionData.RegionHandle, update.RegionData.TimeDilation); + OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation); } } - } - break; - case (byte)PCode.Grass: // FIXME: Handle grass objects - case (byte)PCode.Tree: // FIXME: Handle trees - case (byte)PCode.ParticleSystem: // FIXME: Handle ParticleSystem - default: - break; + break; + case (byte)PCode.Avatar: + if (OnNewAvatar != null) + { + Avatar avatar = new Avatar(); + + string FirstName = ""; + string LastName = ""; + string GroupName = ""; + + //avatar.CollisionPlane = new LLQuaternion(block.ObjectData, 0); + avatar.Position = new LLVector3(block.ObjectData, 16); + avatar.Rotation = new LLQuaternion(block.ObjectData, 52, true); + + // TODO: Parse the rest of the ObjectData byte array fields + + ParseAvName(Helpers.FieldToString(block.NameValue), ref FirstName, ref LastName, ref GroupName); + + avatar.ID = block.FullID; + avatar.LocalID = block.ID; + avatar.Name = FirstName + " " + LastName; + avatar.GroupName = GroupName; + avatar.Online = true; + avatar.CurrentRegion = simulator.Region; + + avatar.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length); + + if (FirstName == Client.Self.FirstName && LastName == Client.Self.LastName) + { + // Update our avatar + Client.Self.LocalID = avatar.LocalID; + Client.Self.Position = avatar.Position; + Client.Self.Rotation = avatar.Rotation; + } + else + { + if (OnNewAvatar != null) + { + OnNewAvatar(simulator, avatar, update.RegionData.RegionHandle, update.RegionData.TimeDilation); + } + } + } + break; + case (byte)PCode.Grass: // FIXME: Handle grass objects + case (byte)PCode.Tree: // FIXME: Handle trees + case (byte)PCode.ParticleSystem: // FIXME: Handle ParticleSystem + default: + break; } } } @@ -521,7 +555,7 @@ namespace libsecondlife int i = 0; bool avatar; - localid = (uint)(block.Data[i++] + (block.Data[i++] << 8) + + localid = (uint)(block.Data[i++] + (block.Data[i++] << 8) + (block.Data[i++] << 16) + (block.Data[i++] << 24)); byte state = block.Data[i++]; @@ -817,7 +851,7 @@ namespace libsecondlife } catch (System.IndexOutOfRangeException e) { - Client.Log("Had a problem decoding an ObjectUpdateCompressed packet: " + + Client.Log("Had a problem decoding an ObjectUpdateCompressed packet: " + e.ToString(), Helpers.LogLevel.Warning); Client.Log(block.ToString(), Helpers.LogLevel.Warning); } diff --git a/libsecondlife-cs/Types.cs b/libsecondlife-cs/Types.cs index 9799e71f..8b6de1b2 100644 --- a/libsecondlife-cs/Types.cs +++ b/libsecondlife-cs/Types.cs @@ -681,6 +681,22 @@ namespace libsecondlife } } + /// + /// Build a quaternion from normalized float values + /// + /// X value from -1.0 to 1.0 + /// Y value from -1.0 to 1.0 + /// Z value from -1.0 to 1.0 + public LLQuaternion(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + + float xyzsum = 1 - X * X - Y * Y - Z * Z; + W = (xyzsum > 0) ? (float)Math.Sqrt(xyzsum) : 0; + } + /// /// ///