From 263db441292956a8210a00c037848165667ab90e Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Mon, 20 Apr 2015 21:30:06 +0200 Subject: Implement llGetBoundingBox fully. Signed-off-by: Michael Cerquoni --- .../Shared/Api/Implementation/LSL_Api.cs | 489 +++++++++++++++++++-- 1 file changed, 447 insertions(+), 42 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 40b7c35..5436888 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -28,6 +28,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; using System.Runtime.Remoting.Lifetime; using System.Text; using System.Threading; @@ -35,7 +37,9 @@ using System.Text.RegularExpressions; using Nini.Config; using log4net; using OpenMetaverse; +using OpenMetaverse.Assets; using OpenMetaverse.Packets; +using OpenMetaverse.Rendering; using OpenSim; using OpenSim.Framework; @@ -182,6 +186,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected bool m_restrictEmail = false; protected ISoundModule m_SoundModule = null; + protected float m_avatarHeightCorrection = 0.2f; + protected bool m_useSimpleBoxesInGetBoundingBox = false; + protected bool m_addStatsInGetBoundingBox = false; + + //LSL Avatar Bounding Box (lABB), lower (1) and upper (2), + //standing (Std), Groundsitting (Grs), Sitting (Sit), + //along X, Y and Z axes, constants (0) and coefficients (1) + protected float m_lABB1StdX0 = -0.275f; + protected float m_lABB2StdX0 = 0.275f; + protected float m_lABB1StdY0 = -0.35f; + protected float m_lABB2StdY0 = 0.35f; + protected float m_lABB1StdZ0 = -0.1f; + protected float m_lABB1StdZ1 = -0.5f; + protected float m_lABB2StdZ0 = 0.1f; + protected float m_lABB2StdZ1 = 0.5f; + protected float m_lABB1GrsX0 = -0.3875f; + protected float m_lABB2GrsX0 = 0.3875f; + protected float m_lABB1GrsY0 = -0.5f; + protected float m_lABB2GrsY0 = 0.5f; + protected float m_lABB1GrsZ0 = -0.05f; + protected float m_lABB1GrsZ1 = -0.375f; + protected float m_lABB2GrsZ0 = 0.5f; + protected float m_lABB2GrsZ1 = 0.0f; + protected float m_lABB1SitX0 = -0.5875f; + protected float m_lABB2SitX0 = 0.1875f; + protected float m_lABB1SitY0 = -0.35f; + protected float m_lABB2SitY0 = 0.35f; + protected float m_lABB1SitZ0 = -0.35f; + protected float m_lABB1SitZ1 = -0.375f; + protected float m_lABB2SitZ0 = -0.25f; + protected float m_lABB2SitZ1 = 0.25f; + //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. private string[] HttpStandardHeaders = @@ -257,6 +293,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (lslConfig != null) { m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); + m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection); + m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox); + m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox); + m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0); + m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0); + m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0); + m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0); + m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0); + m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1); + m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0); + m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1); + m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0); + m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0); + m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0); + m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0); + m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0); + m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1); + m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0); + m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1); + m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0); + m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0); + m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0); + m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0); + m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0); + m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); + m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); + m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -9584,75 +9647,417 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// A partial implementation. + /// Full implementation of llGetBoundingBox according to SL 2015-04-15. + /// http://wiki.secondlife.com/wiki/LlGetBoundingBox /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox - /// So far only valid for standing/flying/ground sitting avatars and single prim objects. - /// If the object has multiple prims and/or a sitting avatar then the bounding - /// box is for the root prim only. + /// Returns local bounding box of avatar without attachments + /// if target is non-seated avatar or prim/mesh in avatar attachment. + /// Returns local bounding box of object including seated avatars + /// if target is seated avatar or prim/mesh in object. + /// Uses meshing of prims for high accuracy + /// or less accurate box models for speed. /// public LSL_List llGetBoundingBox(string obj) { m_host.AddScriptLPS(1); + + // Get target avatar if non-seated avatar or attachment, or prim and object UUID objID = UUID.Zero; + UUID.TryParse(obj, out objID); + ScenePresence agent = World.GetScenePresence(objID); + if (agent != null) + { + if (agent.ParentPart != null) + { + objID = agent.ParentPart.UUID; + agent = null; + } + } + SceneObjectGroup group = null; + SceneObjectPart target = World.GetSceneObjectPart(objID); + if (target != null) + { + group = target.ParentGroup; + if (group.IsAttachment) { + objID = group.AttachedAvatar; + agent = World.GetScenePresence(objID); + group = null; + target = null; + } + } + + // Initialize but break if no target LSL_List result = new LSL_List(); - if (!UUID.TryParse(obj, out objID)) + int groupCount = 0; + int partCount = 0; + int vertexCount = 0; + if (target == null && agent == null) { result.Add(new LSL_Vector()); result.Add(new LSL_Vector()); + if (m_addStatsInGetBoundingBox) + result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); return result; } - ScenePresence presence = World.GetScenePresence(objID); - if (presence != null) + Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); + Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue); + + // Try to get a mesher + IRendering primMesher = null; + List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); + if (renderers.Count > 0) + primMesher = RenderingLoader.LoadRenderer(renderers[0]); + + // Get bounding box of just avatar, seated or not + if (agent != null) + { + bool hasParent = false; + Vector3 lower; + Vector3 upper; + BoundingBoxOfScenePresence(agent, out lower, out upper); + Vector3 offset = Vector3.Zero; + + // Since local bounding box unrotated and untilted, keep it simple + AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + partCount++; + groupCount++; + + // Return lower and upper bounding box corners + result.Add(new LSL_Vector(minPosition)); + result.Add(new LSL_Vector(maxPosition)); + if (m_addStatsInGetBoundingBox) + result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); + return result; + } + // Get bounding box of object including seated avatars + else if (group != null) { - if (presence.ParentID == 0) // not sat on an object + // Merge bounding boxes of all parts (prims and mesh) + foreach (SceneObjectPart part in group.Parts) { - LSL_Vector lower; - LSL_Vector upper; - if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID - == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) + bool hasParent = (!part.IsRoot); + // When requested or if no mesher, keep it simple + if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) { - // This is for ground sitting avatars - float height = presence.Appearance.AvatarHeight / 2.66666667f; - lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); - upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); + AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); } + // Do the full mounty else { - // This is for standing/flying avatars - float height = presence.Appearance.AvatarHeight / 2.0f; - lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); - upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); + Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); + byte[] sculptAsset = null; + if (omvPrim.Sculpt != null) + sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + + // When part is mesh + // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler. + if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) + { + AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); + FacetedMesh mesh = null; + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); + meshAsset = null; + if (mesh != null) + { + AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + mesh = null; + } + } + + // When part is sculpt + // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. + else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + { + IJ2KDecoder imgDecoder = World.RequestModuleInterface(); + if (imgDecoder != null) + { + Image sculpt = imgDecoder.DecodeToImage(sculptAsset); + if (sculpt != null) + { + SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); + sculpt.Dispose(); + if (mesh != null) + { + AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + mesh = null; + } + } + } + } + + // When part is prim + else if (omvPrim.Sculpt == null) + { + SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); + if (mesh != null) + { + AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + mesh = null; + } + } + + // When all else fails, try fallback to simple box + else + { + AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + } } - result.Add(lower); - result.Add(upper); - return result; + partCount++; } + } + + // Merge bounding boxes of seated avatars + foreach (ScenePresence sp in group.GetSittingAvatars()) + { + Vector3 lower; + Vector3 upper; + BoundingBoxOfScenePresence(sp, out lower, out upper); + Vector3 offset = sp.OffsetPosition; + + bool hasParent = true; + // When requested or if no mesher, keep it simple + if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) + { + AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + } + // Do the full mounty else { - // sitting on an object so we need the bounding box of that - // which should include the avatar so set the UUID to the - // UUID of the object the avatar is sat on and allow it to fall through - // to processing an object - SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID); - objID = p.UUID; + // Prim shapes don't do center offsets, so add it here. + offset = offset + (lower + upper) * 0.5f * sp.Rotation; + Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); + SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); + AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); + mesh = null; + } + partCount++; + } + + groupCount++; + + // Return lower and upper bounding box corners + result.Add(new LSL_Vector(minPosition)); + result.Add(new LSL_Vector(maxPosition)); + if (m_addStatsInGetBoundingBox) + result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); + + primMesher = null; + return result; + } + + /// + /// Helper to calculate bounding box of an avatar. + /// + private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) + { + // Adjust from OS model + // avatar height = visual height - 0.2, bounding box height = visual height + // to SL model + // avatar height = visual height, bounding box height = visual height + 0.2 + float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; + + // According to avatar bounding box in SL 2015-04-18: + // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> + // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> + // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> + + // When avatar is sitting + if (sp.ParentPart != null) + { + lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); + upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); + } + // When avatar is groundsitting + else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) + { + lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); + upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); + } + // When avatar is standing or flying + else + { + lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); + upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); + } + } + + /// + /// Helper to approximate a part with a simple box. + /// + private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) + { + // Parse the 8 box corners + for (int i = 0; i < 8; i++) + { + // Calculate each box corner + Vector3 position = corner1; + if ((i & 1) != 0) + position.X = corner2.X; + if ((i & 2) != 0) + position.Y = corner2.Y; + if ((i & 4) != 0) + position.Z = corner2.Z; + // Rotate part unless part is root + if (hasParent) + position = position * rotation; + position = position + offset; + // Adjust lower and upper bounding box corners if needed + lower = Vector3.Min(lower, position); + upper = Vector3.Max(upper, position); + count++; + } + } + + /// + /// Helper to parse a meshed prim and needed especially + /// for accuracy with tortured prims and sculpts. + /// + private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) + { + // Quirk: A meshed box contains 10 instead of the 8 necessary vertices. + if (mesh != null) + { + // Parse each vertex in mesh + foreach (Vertex vertex in mesh.Vertices) + { + Vector3 position = vertex.Position; + position = position * prim.Scale; + // Rotate part unless part is root + if (hasParent) + position = position * prim.Rotation; + position = position + prim.Position; + // Adjust lower and upper bounding box corners if needed + lower = Vector3.Min(lower, position); + upper = Vector3.Max(upper, position); + count++; } } - SceneObjectPart part = World.GetSceneObjectPart(objID); - // Currently only works for single prims without a sitting avatar - if (part != null) + } + + /// + /// Helper to parse mesh because no method exists + /// to parse mesh assets to SimpleMesh. + /// + private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) + { + if (mesh != null) { - Vector3 halfSize = part.Scale / 2.0f; - LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; - LSL_Vector upper = new LSL_Vector(halfSize); - result.Add(lower); - result.Add(upper); - return result; + // Parse each face in mesh + // since vertex array isn't populated. + // This parses each unique vertex 3-6 times. + foreach (Face face in mesh.Faces) + { + // Parse each vertex in face + foreach (Vertex vertex in face.Vertices) + { + Vector3 position = vertex.Position; + position = position * prim.Scale; + // Rotate part unless part is root + if (hasParent) + position = position * prim.Rotation; + position = position + prim.Position; + // Adjust lower and upper bounding box corners if needed + lower = Vector3.Min(lower, position); + upper = Vector3.Max(upper, position); + count++; + } + } } + } - // Not found so return empty values - result.Add(new LSL_Vector()); - result.Add(new LSL_Vector()); - return result; + /// + /// Helper to make up an OpenMetaverse prim + /// needed to create mesh from parts. + /// + private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType) + { + // Initialize and set common parameters + Primitive prim = new OpenMetaverse.Primitive(); + prim.Scale = scale; + prim.Position = position; + prim.Rotation = rotation; + prim.PrimData.PathShearX = 0.0f; + prim.PrimData.PathShearY = 0.0f; + prim.PrimData.PathBegin = 0.0f; + prim.PrimData.PathEnd = 1.0f; + prim.PrimData.PathScaleX = 1.0f; + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.PathTaperX = 0.0f; + prim.PrimData.PathTaperY = 0.0f; + prim.PrimData.PathTwistBegin = 0.0f; + prim.PrimData.PathTwist = 0.0f; + prim.PrimData.ProfileBegin = 0.0f; + prim.PrimData.ProfileEnd = 1.0f; + prim.PrimData.ProfileHollow = 0.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)1; + prim.PrimData.ProfileHole = (HoleType)0; + prim.PrimData.PathCurve = (PathCurve)16; + prim.PrimData.PathRadiusOffset = 0.0f; + prim.PrimData.PathRevolutions = 1.0f; + prim.PrimData.PathSkew = 0.0f; + prim.PrimData.PCode = OpenMetaverse.PCode.Prim; + prim.PrimData.State = (byte)0; + + // Set type specific parameters + switch (primType) + { + // Set specific parameters for box + case ScriptBaseClass.PRIM_TYPE_BOX: + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)1; + prim.PrimData.PathCurve = (PathCurve)16; + break; + // Set specific parameters for cylinder + case ScriptBaseClass.PRIM_TYPE_CYLINDER: + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)0; + prim.PrimData.PathCurve = (PathCurve)16; + break; + // Set specific parameters for prism + case ScriptBaseClass.PRIM_TYPE_PRISM: + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)3; + prim.PrimData.PathCurve = (PathCurve)16; + break; + // Set specific parameters for sphere + case ScriptBaseClass.PRIM_TYPE_SPHERE: + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)5; + prim.PrimData.PathCurve = (PathCurve)32; + break; + // Set specific parameters for torus + case ScriptBaseClass.PRIM_TYPE_TORUS: + prim.PrimData.PathScaleY = 0.5f; + prim.PrimData.ProfileCurve = (ProfileCurve)0; + prim.PrimData.PathCurve = (PathCurve)32; + break; + // Set specific parameters for tube + case ScriptBaseClass.PRIM_TYPE_TUBE: + prim.PrimData.PathScaleY = 0.5f; + prim.PrimData.ProfileCurve = (ProfileCurve)1; + prim.PrimData.PathCurve = (PathCurve)32; + break; + // Set specific parameters for ring + case ScriptBaseClass.PRIM_TYPE_RING: + prim.PrimData.PathScaleY = 0.5f; + prim.PrimData.ProfileCurve = (ProfileCurve)3; + prim.PrimData.PathCurve = (PathCurve)32; + break; + // Set specific parameters for sculpt + case ScriptBaseClass.PRIM_TYPE_SCULPT: + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)5; + prim.PrimData.PathCurve = (PathCurve)32; + break; + // Default to specific parameters for box + default: + prim.PrimData.PathScaleY = 1.0f; + prim.PrimData.ProfileCurve = (ProfileCurve)1; + prim.PrimData.PathCurve = (PathCurve)16; + break; + } + + return prim; } public LSL_Vector llGetGeometricCenter() -- cgit v1.1 From f11720d71fee66b7dc902c3a6632e571824e2288 Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Mon, 20 Apr 2015 05:36:39 +0100 Subject: Enable grab feature (Ctrl+Drag) for non-physical link-sets and add code to handle spin (Ctrl+Shift+Drag) This patch fixes permission issues with dragging scripted objects. As on LL grid, scripted prims can not be dragged now. Also after dragging, the group was not marked as updated. This meant that after the region was restarted the group would revert to its original position. Signed-off-by: Michael Cerquoni --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0a1a226..75da299 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2672,20 +2672,26 @@ namespace OpenSim.Region.Framework.Scenes } else { - //NonPhysicalGrabMovement(pos); + NonPhysicalGrabMovement(pos); } } else { - //NonPhysicalGrabMovement(pos); + NonPhysicalGrabMovement(pos); } } } + /// + /// Apply possition for grabbing non-physical linksets (ctrl+drag) + /// + /// New Position public void NonPhysicalGrabMovement(Vector3 pos) { - AbsolutePosition = pos; - m_rootPart.SendTerseUpdateToAllClients(); + if((m_rootPart.Flags & PrimFlags.Scripted) == 0) + { + UpdateGroupPosition(pos); + } } /// @@ -2781,17 +2787,29 @@ namespace OpenSim.Region.Framework.Scenes } else { - //NonPhysicalSpinMovement(pos); + NonPhysicalSpinMovement(newOrientation); } } else { - //NonPhysicalSpinMovement(pos); + NonPhysicalSpinMovement(newOrientation); } } } /// + /// Apply rotation for spinning non-physical linksets (ctrl+shift+drag) + /// + /// New Rotation + private void NonPhysicalSpinMovement(Quaternion newOrientation) + { + if ((m_rootPart.Flags & PrimFlags.Scripted) == 0) + { + UpdateGroupRotationR(newOrientation); + } + } + + /// /// Set the name of a prim /// /// -- cgit v1.1 From e855c8e7118823808f6af89f878f81858fbf35c6 Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Fri, 20 Mar 2015 19:12:43 +0100 Subject: Allow setting profilecut diff to 0.02 from scripts just like from viewer. Signed-off-by: Michael Cerquoni --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5436888..e20e4c4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7788,13 +7788,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { profilecut.y = 1f; } - if (profilecut.y - profilecut.x < 0.05f) + if (profilecut.y - profilecut.x < 0.02f) { - profilecut.x = profilecut.y - 0.05f; + profilecut.x = profilecut.y - 0.02f; if (profilecut.x < 0.0f) { profilecut.x = 0.0f; - profilecut.y = 0.05f; + profilecut.y = 0.02f; } } shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); -- cgit v1.1 From cde4e7ec865b1e6c933fad0f6b14e6df55123f0c Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Sat, 25 Apr 2015 05:39:20 +0100 Subject: Fix the click to buy prim dialog not being displayed with alpha viewers after recent changes to viewer code by LL. Recent viewer changes by linden lab now require more information when requesting prim tooltip data. The object properties must now be sent when the viewer requests the object family properties used to display the tool tip. Thanks to Liru for finding the viewer commit that broke this feature in OS. Signed-off-by: BlueWall --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 311dd31..855342f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4465,7 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1 From d80230adcdd26a7f512355df256cc5c9c5e3d0e6 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Mon, 27 Apr 2015 15:46:09 -0500 Subject: Revert "Fix the click to buy prim dialog not being displayed with alpha viewers after recent changes to viewer code by LL." See: http://opensimulator.org/mantis/view.php?id=7426#c28089 Reverting this commit due to unwanted effects. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 855342f..311dd31 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4465,7 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1 From 38459104eb7d3484d17bc764c500fb9f4026c49a Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 28 Apr 2015 09:36:56 -0500 Subject: Revert "Revert "Fix the click to buy prim dialog not being displayed with alpha viewers after recent changes to viewer code by LL."" This brings back the fix for recent viewer click to buy prim dialog which was reverted after some reports of objects being altered when touched. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 311dd31..855342f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4465,7 +4465,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { uint priority = 0; // time based ordering only lock (m_entityProps.SyncRoot) - m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); + m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true)); } private void ResendPropertyUpdate(ObjectPropertyUpdate update) -- cgit v1.1 From e171ae899d3b78072f368de357dadeeae8808f8d Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 28 Apr 2015 17:24:54 -0500 Subject: Revert "Enable grab feature (Ctrl+Drag) for non-physical link-sets and add code to handle spin (Ctrl+Shift+Drag)" We found that linksets can move if the root prim is unscripted. Will revert this until a fix can be implemented. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 30 +++++----------------- 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 75da299..0a1a226 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2672,26 +2672,20 @@ namespace OpenSim.Region.Framework.Scenes } else { - NonPhysicalGrabMovement(pos); + //NonPhysicalGrabMovement(pos); } } else { - NonPhysicalGrabMovement(pos); + //NonPhysicalGrabMovement(pos); } } } - /// - /// Apply possition for grabbing non-physical linksets (ctrl+drag) - /// - /// New Position public void NonPhysicalGrabMovement(Vector3 pos) { - if((m_rootPart.Flags & PrimFlags.Scripted) == 0) - { - UpdateGroupPosition(pos); - } + AbsolutePosition = pos; + m_rootPart.SendTerseUpdateToAllClients(); } /// @@ -2787,29 +2781,17 @@ namespace OpenSim.Region.Framework.Scenes } else { - NonPhysicalSpinMovement(newOrientation); + //NonPhysicalSpinMovement(pos); } } else { - NonPhysicalSpinMovement(newOrientation); + //NonPhysicalSpinMovement(pos); } } } /// - /// Apply rotation for spinning non-physical linksets (ctrl+shift+drag) - /// - /// New Rotation - private void NonPhysicalSpinMovement(Quaternion newOrientation) - { - if ((m_rootPart.Flags & PrimFlags.Scripted) == 0) - { - UpdateGroupRotationR(newOrientation); - } - } - - /// /// Set the name of a prim /// /// -- cgit v1.1 From 59778cfc2abc807792b64e9392ad3009aaf07ecb Mon Sep 17 00:00:00 2001 From: Steven Zielinski Date: Tue, 21 Apr 2015 15:33:54 -0400 Subject: Added in all metrics for Phase 1 except for Time Dilation. Test Plan: Tested on local opensim and firestorm. Not tested with JSON stats reporter. Reviewers: rlouden Reviewed By: rlouden Differential Revision: http://cr.irl.ucf.edu/D269 Signed-off-by: Diva Canto --- OpenSim/Region/Framework/Scenes/Scene.cs | 104 ++++++++++++++++- .../Region/Framework/Scenes/SimStatsReporter.cs | 123 +++++++++++++++++++-- 2 files changed, 218 insertions(+), 9 deletions(-) mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/Scene.cs mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SimStatsReporter.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs old mode 100644 new mode 100755 index 4715558..906c862 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1107,7 +1107,27 @@ namespace OpenSim.Region.Framework.Scenes #endregion Interest Management - StatsReporter = new SimStatsReporter(this); + // Acquire the statistics section of the OpenSim.ini file located + // in the bin directory + IConfig statisticsConfig = m_config.Configs["Statistics"]; + + // Confirm that the statistics section existed in the configuration + // file + if (statisticsConfig != null) + { + // Create the StatsReporter using the number of frames to store + // for the frame time statistics, or 10 frames if the config + // file doesn't contain a value + StatsReporter = new SimStatsReporter(this, + statisticsConfig.GetInt("NumberOfFrames", 10)); + } + else + { + // Create a StatsReporter with the current scene and a default + // 10 frames stored for the frame time statistics + StatsReporter = new SimStatsReporter(this); + } + StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; @@ -1607,6 +1627,21 @@ namespace OpenSim.Region.Framework.Scenes float physicsFPS = 0f; int previousFrameTick, tmpMS; + // These variables will be used to save the precise frame time using the + // Stopwatch class of Microsoft SDK; the times are recorded at the start + // and end of a particular section of code, and then used to calculate + // the frame times, which are the sums of the sections for each given name + double preciseTotalFrameTime = 0.0; + double preciseSimFrameTime = 0.0; + double precisePhysicsFrameTime = 0.0; + Stopwatch totalFrameStopwatch = new Stopwatch(); + Stopwatch simFrameStopwatch = new Stopwatch(); + Stopwatch physicsFrameStopwatch = new Stopwatch(); + + // Begin the stopwatch to keep track of the time that the frame + // started running to determine how long the frame took to complete + totalFrameStopwatch.Start(); + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { ++Frame; @@ -1622,25 +1657,62 @@ namespace OpenSim.Region.Framework.Scenes // Apply taints in terrain module to terrain in physics scene if (Frame % m_update_terrain == 0) { + // At several points inside the code there was a need to + // create a more precise measurement of time elapsed. + // This led to the addition of variables that have a + // similar function and thus remain tightly connected to + // their original counterparts. However, the original + // code is not receiving comments from our group because + // we don't feel right modifying the code to that degree + // at this point in time, the precise values all begin + // with the keyword precise tmpMS = Util.EnvironmentTickCount(); + + simFrameStopwatch.Start(); UpdateTerrain(); + + // Get the simulation frame time that the avatar force + // input took + simFrameStopwatch.Stop(); + preciseSimFrameTime = + simFrameStopwatch.Elapsed.TotalMilliseconds; terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); } tmpMS = Util.EnvironmentTickCount(); + + // Begin the stopwatch to track the time to prepare physics + physicsFrameStopwatch.Start(); if (PhysicsEnabled && Frame % m_update_physics == 0) m_sceneGraph.UpdatePreparePhysics(); + + // Get the time it took to prepare the physics, this + // would report the most precise time that physics was + // running on the machine and should the physics not be + // enabled will report the time it took to check if physics + // was enabled + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime = + physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); // Apply any pending avatar force input to the avatar's velocity tmpMS = Util.EnvironmentTickCount(); + simFrameStopwatch.Restart(); if (Frame % m_update_entitymovement == 0) m_sceneGraph.UpdateScenePresenceMovement(); + + // Get the simulation frame time that the avatar force input + // took + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; agentMS = Util.EnvironmentTickCountSubtract(tmpMS); // Perform the main physics update. This will do the actual work of moving objects and avatars according to their // velocity tmpMS = Util.EnvironmentTickCount(); + physicsFrameStopwatch.Restart(); if (Frame % m_update_physics == 0) { if (PhysicsEnabled) @@ -1649,8 +1721,16 @@ namespace OpenSim.Region.Framework.Scenes if (SynchronizeScene != null) SynchronizeScene(this); } + + // Add the main physics update time to the prepare physics + // time + physicsFrameStopwatch.Stop(); + precisePhysicsFrameTime += + physicsFrameStopwatch.Elapsed.TotalMilliseconds; physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); + // Start the stopwatch for the remainder of the simulation + simFrameStopwatch.Restart(); tmpMS = Util.EnvironmentTickCount(); // Check if any objects have reached their targets @@ -1738,6 +1818,11 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerRegionHeartbeatEnd(this); otherMS = eventMS + backupMS + terrainMS + landMS; + // Get the elapsed time for the simulation frame + simFrameStopwatch.Stop(); + preciseSimFrameTime += + simFrameStopwatch.Elapsed.TotalMilliseconds; + if (!UpdateOnTimer) { Watchdog.UpdateThread(); @@ -1754,6 +1839,14 @@ namespace OpenSim.Region.Framework.Scenes spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); } + // Get the total frame time + totalFrameStopwatch.Stop(); + preciseTotalFrameTime = + totalFrameStopwatch.Elapsed.TotalMilliseconds; + + // Restart the stopwatch for the total time of the next frame + totalFrameStopwatch.Restart(); + previousFrameTick = m_lastFrameTick; frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); m_lastFrameTick = Util.EnvironmentTickCount(); @@ -1771,6 +1864,15 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.AddSpareMS(spareMS); StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + // Send the correct time values to the stats reporter for the + // frame times + StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, + preciseSimFrameTime, precisePhysicsFrameTime, 0.0); + + // Send the correct number of frames that the physics library + // has processed to the stats reporter + StatsReporter.addPhysicsFrame(1); + // Optionally warn if a frame takes double the amount of time that it should. if (DebugUpdates && Util.EnvironmentTickCountSubtract( diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs old mode 100644 new mode 100755 index 8f1e345..6182bcd --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -213,6 +213,27 @@ namespace OpenSim.Region.Framework.Scenes private int m_objectCapacity = 45000; + // This is the number of frames that will be stored and then averaged for + // the Total, Simulation, Physics, and Network Frame Time; It is set to + // 10 by default but can be changed by the OpenSim.ini configuration file + // NumberOfFrames parameter + private int m_numberFramesStored = 10; + + // The arrays that will hold the time it took to run the past N frames, + // where N is the num_frames_to_average given by the configuration file + private double[] m_totalFrameTimeMilliseconds; + private double[] m_simulationFrameTimeMilliseconds; + private double[] m_physicsFrameTimeMilliseconds; + private double[] m_networkFrameTimeMilliseconds; + + // The location of the next time in milliseconds that will be + // (over)written when the next frame completes + private int m_nextLocation = 0; + + // The correct number of frames that have completed since the last stats + // update for physics + private int m_numberPhysicsFrames; + private Scene m_scene; private RegionInfo ReportingRegion; @@ -223,6 +244,13 @@ namespace OpenSim.Region.Framework.Scenes public SimStatsReporter(Scene scene) { + // Initialize the different frame time arrays to the correct sizes + m_totalFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_simulationFrameTimeMilliseconds = new + double[m_numberFramesStored]; + m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_networkFrameTimeMilliseconds = new double[m_numberFramesStored]; + m_scene = scene; m_reportedFpsCorrectionFactor = scene.MinFrameSeconds * m_nominalReportedFps; m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); @@ -256,6 +284,13 @@ namespace OpenSim.Region.Framework.Scenes StatsManager.RegisterStat(SlowFramesStat); } + public SimStatsReporter(Scene scene, int numberOfFrames) : this (scene) + { + // Store the number of frames from the OpenSim.ini configuration + // file + m_numberFramesStored = numberOfFrames; + } + public void Close() { m_report.Elapsed -= TriggerStatsHeartbeat; @@ -289,6 +324,11 @@ namespace OpenSim.Region.Framework.Scenes private void statsHeartBeat(object sender, EventArgs e) { + double totalSumFrameTime; + double simulationSumFrameTime; + double physicsSumFrameTime; + double networkSumFrameTime; + if (!m_scene.Active) return; @@ -314,14 +354,21 @@ namespace OpenSim.Region.Framework.Scenes #region various statistic googly moogly + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window, this will be done as a + // new section given the title of our current project // We're going to lie about the FPS because we've been lying since 2008. The actual FPS is currently // locked at a maximum of 11. Maybe at some point this can change so that we're not lying. - int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); - + //int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); + int reportedFPS = m_fps; + // save the reported value so there is something available for llGetRegionFPS lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; - float physfps = ((m_pfps / 1000)); + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window + //float physfps = ((m_pfps / 1000)); + float physfps = m_numberPhysicsFrames; //if (physfps > 600) //physfps = physfps - (physfps - 600); @@ -364,6 +411,26 @@ namespace OpenSim.Region.Framework.Scenes sb[i] = new SimStatsPacket.StatBlock(); } + // Resetting the sums of the frame times to prevent any errors + // in calculating the moving average for frame time + totalSumFrameTime = 0; + simulationSumFrameTime = 0; + physicsSumFrameTime = 0; + networkSumFrameTime = 0; + + // Loop through all the frames that were stored for the current + // heartbeat to process the moving average of frame times + for (int i = 0; i < m_numberFramesStored; i++) + { + // Sum up each frame time in order to calculate the moving + // average of frame time + totalSumFrameTime += m_totalFrameTimeMilliseconds[i]; + simulationSumFrameTime += + m_simulationFrameTimeMilliseconds[i]; + physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i]; + networkSumFrameTime += m_networkFrameTimeMilliseconds[i]; + } + sb[0].StatID = (uint) Stats.TimeDilation; sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); @@ -388,21 +455,31 @@ namespace OpenSim.Region.Framework.Scenes sb[7].StatID = (uint) Stats.ActivePrim; sb[7].StatValue = m_activePrim; + // ORIGINAL code commented out until we have time to add our own + // statistics to the statistics window sb[8].StatID = (uint)Stats.FrameMS; - sb[8].StatValue = m_frameMS / framesUpdated; + //sb[8].StatValue = m_frameMS / framesUpdated; + sb[8].StatValue = (float) totalSumFrameTime / + m_numberFramesStored; sb[9].StatID = (uint)Stats.NetMS; - sb[9].StatValue = m_netMS / framesUpdated; + //sb[9].StatValue = m_netMS / framesUpdated; + sb[9].StatValue = (float) networkSumFrameTime / + m_numberFramesStored; sb[10].StatID = (uint)Stats.PhysicsMS; - sb[10].StatValue = m_physicsMS / framesUpdated; + //sb[10].StatValue = m_physicsMS / framesUpdated; + sb[10].StatValue = (float) physicsSumFrameTime / + m_numberFramesStored; sb[11].StatID = (uint)Stats.ImageMS ; sb[11].StatValue = m_imageMS / framesUpdated; sb[12].StatID = (uint)Stats.OtherMS; - sb[12].StatValue = m_otherMS / framesUpdated; - + //sb[12].StatValue = m_otherMS / framesUpdated; + sb[12].StatValue = (float) simulationSumFrameTime / + m_numberFramesStored; + sb[13].StatID = (uint)Stats.InPacketsPerSecond; sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); @@ -475,6 +552,10 @@ namespace OpenSim.Region.Framework.Scenes private void ResetValues() { + // Reset the number of frames that the physics library has + // processed since the last stats report + m_numberPhysicsFrames = 0; + m_timeDilation = 0; m_fps = 0; m_pfps = 0; @@ -605,6 +686,32 @@ namespace OpenSim.Region.Framework.Scenes m_otherMS += ms; } + public void addPhysicsFrame(int frames) + { + // Add the number of physics frames to the correct total physics + // frames + m_numberPhysicsFrames += frames; + } + + public void addFrameTimeMilliseconds(double total, double simulation, + double physics, double network) + { + // Save the frame times from the current frame into the appropriate + // arrays + m_totalFrameTimeMilliseconds[m_nextLocation] = total; + m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation; + m_physicsFrameTimeMilliseconds[m_nextLocation] = physics; + m_networkFrameTimeMilliseconds[m_nextLocation] = network; + + // Update to the next location in the list + m_nextLocation++; + + // Since the list will begin to overwrite the oldest frame values + // first, the next location needs to loop back to the beginning of the + // list whenever it reaches the end + m_nextLocation = m_nextLocation % m_numberFramesStored; + } + public void AddPendingDownloads(int count) { m_pendingDownloads += count; -- cgit v1.1 From da32512ea449c2de2d4a6069f899fbd4a8bb03fa Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 29 Apr 2015 18:47:17 -0700 Subject: Updated all occurrences of AssemblyVersion("0.8.1.*") to AssemblyVersion("0.8.2.*") --- OpenSim/Addons/Groups/Properties/AssemblyInfo.cs | 2 +- OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs | 2 +- OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs | 2 +- .../RegionModulesController/Properties/AssemblyInfo.cs | 2 +- OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs | 2 +- OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs | 2 +- OpenSim/Data/MySQL/Properties/AssemblyInfo.cs | 2 +- OpenSim/Data/Null/Properties/AssemblyInfo.cs | 2 +- OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs | 2 +- OpenSim/Data/Properties/AssemblyInfo.cs | 2 +- OpenSim/Data/SQLite/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/AssemblyInfo.cs | 2 +- OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/Communications/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/Console/AssemblyInfo.cs | 2 +- OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs | 2 +- OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/Application/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/Framework/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs | 2 +- .../Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/Physics/Manager/AssemblyInfo.cs | 2 +- OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs | 2 +- OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs | 2 +- OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs | 2 +- .../ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs | 2 +- OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs | 2 +- OpenSim/Server/Base/Properties/AssemblyInfo.cs | 2 +- OpenSim/Server/Handlers/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/AssetService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/Base/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/Connectors/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/Friends/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/GridService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs | 2 +- OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs | 2 +- OpenSim/Tools/Configger/Properties/AssemblyInfo.cs | 2 +- OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs | 2 +- 61 files changed, 61 insertions(+), 61 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs index 5ad087a..0a7fb5f 100644 --- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs index 3868912..3e993b4 100644 --- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs +++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs index 0ed47a3..6c3c3e3 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs @@ -63,7 +63,7 @@ using Mono.Addins; // by using the '*' as shown below: // [assembly: AssemblyVersion("0.7.6.*")] -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs index d14938f..021209f 100644 --- a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs +++ b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs index ffeff3a..443e323 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs index 296cb03..3579649 100644 --- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs +++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs index 249842c..b46d175 100644 --- a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs +++ b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs @@ -61,5 +61,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Data/Null/Properties/AssemblyInfo.cs b/OpenSim/Data/Null/Properties/AssemblyInfo.cs index 13e28a8..a827bd0 100644 --- a/OpenSim/Data/Null/Properties/AssemblyInfo.cs +++ b/OpenSim/Data/Null/Properties/AssemblyInfo.cs @@ -61,5 +61,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs index 1c65dbe..1e88b2c 100644 --- a/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs +++ b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs @@ -61,5 +61,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Data/Properties/AssemblyInfo.cs b/OpenSim/Data/Properties/AssemblyInfo.cs index 4e41308..b1f234b 100644 --- a/OpenSim/Data/Properties/AssemblyInfo.cs +++ b/OpenSim/Data/Properties/AssemblyInfo.cs @@ -61,5 +61,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs index 2befd13..d2e62d2 100644 --- a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs +++ b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs @@ -61,5 +61,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs index 5a15568..a797424 100644 --- a/OpenSim/Framework/AssemblyInfo.cs +++ b/OpenSim/Framework/AssemblyInfo.cs @@ -59,4 +59,4 @@ using System.Runtime.InteropServices; // Revision // -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs index 26d0351..cd182d6 100644 --- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs index 907cebd..b398167 100644 --- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs @@ -61,5 +61,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs index 4e50e44..67af471 100644 --- a/OpenSim/Framework/Console/AssemblyInfo.cs +++ b/OpenSim/Framework/Console/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs index ee82753..b08e4f7 100644 --- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs index 4341560..3bcbe2f 100644 --- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs index e7efdf4..1b2519c 100644 --- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs index 11573d2..0cce722 100644 --- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs index ddb7e59..63335bd 100644 --- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Application/Properties/AssemblyInfo.cs b/OpenSim/Region/Application/Properties/AssemblyInfo.cs index 650425b..8652312 100644 --- a/OpenSim/Region/Application/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/Application/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: AddinRoot("OpenSim", OpenSim.VersionInfo.VersionNumber)] [assembly: ImportAddinAssembly("OpenSim.Framework.dll")] diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs index 3bc0be8..264eaa3 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs index 8ce1b85..8795c0c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs index 1b1b319..64532df 100644 --- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs index 637387a..e60d3ae 100644 --- a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs index fd9ab3d..97dea1f 100644 --- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs index d028374..f8ad958 100644 --- a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.Region.OptionalModules", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs index eba0675..7d054dd 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs index 4de5b47..4f90eee 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs index 1486ba8..c5867b2 100644 --- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs index 202ef20..33f60e4 100644 --- a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs index 2b083fe..ec968c0 100644 --- a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs index b95f7f4..076da78 100644 --- a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs index 125d38a..fc1ffba 100644 --- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("0.8.1.*")] +[assembly : AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs index e8b29f9..11b89d2 100644 --- a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.RegionModules.RegionCombinerModule", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs index d02c91c..4708473 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs index 31acd44..4df09ef 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs index af7ee26..3eaaed0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs index 03612ef..0094af6 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs @@ -30,7 +30,7 @@ using Mono.Addins; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] [assembly: Addin("OpenSim.Region.ScriptEngine.XEngine", OpenSim.VersionInfo.VersionNumber)] [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs index 58fa66f..9fac53e 100644 --- a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs index 0d583f0..e819a2b 100644 --- a/OpenSim/Server/Base/Properties/AssemblyInfo.cs +++ b/OpenSim/Server/Base/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs index 04fe41a..780e454 100644 --- a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs +++ b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs index 96391aa..9717319 100644 --- a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs index 46fc1d5..8c63adc 100644 --- a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs index e04ea3f..ce91b56 100644 --- a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs index cf419ff..1778863 100644 --- a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs index 328e011..a3fb11b 100644 --- a/OpenSim/Services/Base/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Base/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs index bb78cfd..2af2ec1 100644 --- a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs index 3a50af3..ca16f08 100644 --- a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs index d47e877..f258f94 100644 --- a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs index 6703b3c..ebe3c44 100644 --- a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs index 5294a50..a565729 100644 --- a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs index b4fd068..a2f6c4f 100644 --- a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs index 094e515..6a1187c 100644 --- a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs index ea03b56..4dc492a 100644 --- a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs index 14dc990..e5f1bf9 100644 --- a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs index ae122e4..9ef0ff3 100644 --- a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs index 9d031d0..33933a0 100644 --- a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs index 7e92d76..b97c977 100644 --- a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs +++ b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs index c470703..e88f0f5 100644 --- a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs +++ b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] diff --git a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs index c0c2b5d..87af19a 100644 --- a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs +++ b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.8.1.*")] +[assembly: AssemblyVersion("0.8.2.*")] -- cgit v1.1 From 4211309ec72bafc69c0f6b1329cbd6c1373c5545 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 2 May 2015 10:27:57 -0700 Subject: Corrected typo in namespace --- OpenSim/Services/Connectors/Estate/EstateDataConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs index 37f9374..6412bcd 100644 --- a/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs +++ b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs @@ -40,7 +40,7 @@ using OpenSim.Services.Connectors; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; -namespace OpenSim.Service.Connectors +namespace OpenSim.Services.Connectors { public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService { -- cgit v1.1 From 365f46bfa91245e6e277a180dc6bbf757ea2540f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 2 May 2015 20:40:37 -0700 Subject: Mantis #7514 Mono bug introduces double xmlns attribute names when rewriting the asset in HGAssetService, e.g. . Solution: remove all attributes before saving. --- .../Framework/Serialization/External/ExternalRepresentationUtils.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index 6debf65..a293388 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs @@ -136,6 +136,9 @@ namespace OpenSim.Framework.Serialization.External foreach (XmlNode sop in sops) { + // Due to mono bug, we're removing all xmlns attributes + sop.Attributes.RemoveAll(); + UserAccount creator = null; bool hasCreatorData = false; XmlNodeList nodes = sop.ChildNodes; -- cgit v1.1 From 09edc9619af66b2705dbb4e28e3ffc1772d9adc0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 2 May 2015 22:15:26 -0700 Subject: It wasn't that. Revert "Mantis #7514" This reverts commit 365f46bfa91245e6e277a180dc6bbf757ea2540f. --- .../Framework/Serialization/External/ExternalRepresentationUtils.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index a293388..6debf65 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs @@ -136,9 +136,6 @@ namespace OpenSim.Framework.Serialization.External foreach (XmlNode sop in sops) { - // Due to mono bug, we're removing all xmlns attributes - sop.Attributes.RemoveAll(); - UserAccount creator = null; bool hasCreatorData = false; XmlNodeList nodes = sop.ChildNodes; -- cgit v1.1 From 877371411a9e997b0b11f45c410438ae2bb73f16 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 2 May 2015 22:18:58 -0700 Subject: Mantis #7514 I think this is it -- a bug introduced back in October, where the prefix and name space were being added twice on HG asset posts bu simulators. --- OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index 75f0774..c2010b1 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -205,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { case XmlNodeType.Attribute: // Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name); - writer.WriteAttributeString(reader.Prefix, reader.Name, reader.NamespaceURI, reader.Value); + writer.WriteAttributeString(reader.Name, reader.Value); break; case XmlNodeType.CDATA: @@ -228,7 +228,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (reader.HasAttributes) { while (reader.MoveToNextAttribute()) - writer.WriteAttributeString(reader.Prefix, reader.Name, reader.NamespaceURI, reader.Value); + writer.WriteAttributeString(reader.Name, reader.Value); reader.MoveToElement(); } -- cgit v1.1 From 60e719286bc82cf9353e508af14fe3252eeddc45 Mon Sep 17 00:00:00 2001 From: dahlia Date: Sun, 3 May 2015 17:05:48 -0700 Subject: Make Meshmerizer mesh cache static so it can be shared across class instances --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index d96de4a..24983ab 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -84,7 +84,8 @@ namespace OpenSim.Region.Physics.Meshing private List> mConvexHulls = null; private List mBoundingHull = null; - private Dictionary m_uniqueMeshes = new Dictionary(); + // Mesh cache. Static so it can be shared across instances of this class + private static Dictionary m_uniqueMeshes = new Dictionary(); public Meshmerizer(IConfigSource config) { -- cgit v1.1 From 73efb1633f61d9ad01ee58ae3e2704283a57ed52 Mon Sep 17 00:00:00 2001 From: dahlia Date: Sun, 3 May 2015 19:54:03 -0700 Subject: lock collision mesh cache when accessing --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 24983ab..42231b5 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -928,8 +928,11 @@ namespace OpenSim.Region.Physics.Meshing if (shouldCache) { key = primShape.GetMeshKey(size, lod); - if (m_uniqueMeshes.TryGetValue(key, out mesh)) - return mesh; + lock (m_uniqueMeshes) + { + if (m_uniqueMeshes.TryGetValue(key, out mesh)) + return mesh; + } } if (size.X < 0.01f) size.X = 0.01f; @@ -955,7 +958,10 @@ namespace OpenSim.Region.Physics.Meshing if (shouldCache) { - m_uniqueMeshes.Add(key, mesh); + lock (m_uniqueMeshes) + { + m_uniqueMeshes.Add(key, mesh); + } } } -- cgit v1.1 From 30f9e5372e7b999ace8334825237a3512c9e40fb Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 3 May 2015 21:56:41 -0700 Subject: Only send parcel layer data around the point of interest. Can be disabled by setting [LandManagement]LimitParcelLayerUpdateDistance=false New parameters added to OpenSimDefaults for the distance and enablement. --- .../CoreModules/World/Land/LandManagementModule.cs | 84 ++++++++++++++++++++-- 1 file changed, 79 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 13485bf..25e1454 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -98,11 +98,17 @@ namespace OpenSim.Region.CoreModules.World.Land // caches ExtendedLandData private Cache parcelInfoCache; + /// /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. /// private Dictionary forcedPosition = new Dictionary(); + // Enables limiting parcel layer info transmission when doing simple updates + private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } + // "View distance" for sending parcel layer info if asked for from a view point in the region + private int parcelLayerViewDistance { get; set; } + #region INonSharedRegionModule Members public Type ReplaceableInterface @@ -112,6 +118,14 @@ namespace OpenSim.Region.CoreModules.World.Land public void Initialise(IConfigSource source) { + shouldLimitParcelLayerInfoToViewDistance = true; + parcelLayerViewDistance = 128; + IConfig landManagementConfig = source.Configs["LandManagement"]; + if (landManagementConfig != null) + { + shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); + parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); + } } public void AddRegion(Scene scene) @@ -1129,11 +1143,26 @@ namespace OpenSim.Region.CoreModules.World.Land #region Parcel Updating + // Send parcel layer info for the whole region + public void SendParcelOverlay(IClientAPI remote_client) + { + SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize); + } + /// - /// Where we send the ParcelOverlay packet to the client + /// Send the parcel overlay blocks to the client. We send the overlay packets + /// around a location and limited by the 'parcelLayerViewDistance'. This number + /// is usually 128 and the code is arranged so it sends all the parcel overlay + /// information for a whole region if the region is legacy sized (256x256). If + /// the region is larger, only the parcel layer information is sent around + /// the point specified. This reduces the problem of parcel layer information + /// blocks increasing exponentially as region size increases. /// /// The object representing the client - public void SendParcelOverlay(IClientAPI remote_client) + /// X position in the region to send surrounding parcel layer info + /// y position in the region to send surrounding parcel layer info + /// Distance from x,y position to send parcel layer info + private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance) { const int LAND_BLOCKS_PER_PACKET = 1024; @@ -1141,15 +1170,58 @@ namespace OpenSim.Region.CoreModules.World.Land int byteArrayCount = 0; int sequenceID = 0; + int xLow = 0; + int xHigh = (int)m_scene.RegionInfo.RegionSizeX; + int yLow = 0; + int yHigh = (int)m_scene.RegionInfo.RegionSizeY; + + if (shouldLimitParcelLayerInfoToViewDistance) + { + // Compute view distance around the given point + int txLow = xPlace - layerViewDistance; + int txHigh = xPlace + layerViewDistance; + // If the distance is outside the region area, move the view distance to ba all in the region + if (txLow < xLow) + { + txLow = xLow; + txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh); + } + if (txHigh > xHigh) + { + txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); + txHigh = xHigh; + } + xLow = txLow; + xHigh = txHigh; + + int tyLow = yPlace - layerViewDistance; + int tyHigh = yPlace + layerViewDistance; + if (tyLow < yLow) + { + tyLow = yLow; + tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh); + } + if (tyHigh > yHigh) + { + tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2)); + tyHigh = yHigh; + } + yLow = tyLow; + yHigh = tyHigh; + } + // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>", + // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh); + // Layer data is in landUnit (4m) chunks - for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) + for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) { - for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) + for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) { byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client); byteArrayCount++; if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) { + // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); remote_client.SendLandParcelOverlay(byteArray, sequenceID); byteArrayCount = 0; sequenceID++; @@ -1162,6 +1234,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (byteArrayCount != 0) { remote_client.SendLandParcelOverlay(byteArray, sequenceID); + // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); } } @@ -1265,7 +1338,8 @@ namespace OpenSim.Region.CoreModules.World.Land temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); } - SendParcelOverlay(remote_client); + // Also send the layer data around the point of interest + SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); } public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) -- cgit v1.1 From 43b8bd0c35c1d7ca0c97a4e64fe255943148d333 Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Sun, 3 May 2015 07:50:13 +0200 Subject: Implement llCastRay fully, simplified. --- .../Shared/Api/Implementation/LSL_Api.cs | 760 ++++++++++++++++++++- 1 file changed, 759 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e20e4c4..cf1bd2b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -218,6 +218,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_lABB2SitZ0 = -0.25f; protected float m_lABB2SitZ1 = 0.25f; + protected float m_primSafetyCoeffX = 2.414214f; + protected float m_primSafetyCoeffY = 2.414214f; + protected float m_primSafetyCoeffZ = 1.618034f; + protected float m_floatToleranceInCastRay = 0.000001f; + protected float m_floatTolerance2InCastRay = 0.0001f; + protected int m_maxHitsInCastRay = 16; + protected int m_maxHitsPerPrimInCastRay = 16; + protected int m_maxHitsPerObjectInCastRay = 16; + protected bool m_detectExitsInCastRay = false; + protected bool m_filterPartsInCastRay = false; + protected bool m_doAttachmentsInCastRay = false; + protected bool m_useCastRayV1 = true; + //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. private string[] HttpStandardHeaders = @@ -320,6 +333,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); + m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); + m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); + m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); + m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); + m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); + m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); + m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); + m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); + m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); + m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); + m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); + m_useCastRayV1 = lslConfig.GetBoolean("UseLlCastRayV1", m_useCastRayV1); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -13738,7 +13763,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return contacts[0]; } - public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRayV1(LSL_Vector start, LSL_Vector end, LSL_List options) { LSL_List list = new LSL_List(); @@ -13929,6 +13954,739 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return list; } + /// + /// Full implementation of llCastRay similar to SL 2015-04-21. + /// http://wiki.secondlife.com/wiki/LlCastRay + /// Uses pure geometry, bounding shapes, meshing and no physics + /// for prims, sculpts, meshes, avatars and terrain. + /// Implements all flags, reject types and data flags. + /// Can handle both objects/groups and prims/parts, by config. + /// May give poor results with multi-part meshes where "root" + /// part doesn't dominate, owing to "guessed" bounding boxes. + /// May sometimes be inaccurate owing to calculation precision + /// and a bug in libopenmetaverse PrimMesher. + /// + public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + { + // Use llCastRay v1 if configured + if (m_useCastRayV1) + return llCastRayV1(start, end, options); + + // Initialize + m_host.AddScriptLPS(1); + List rayHits = new List(); + LSL_List result = new LSL_List(); + float tol = m_floatToleranceInCastRay; + float tol2 = m_floatTolerance2InCastRay; + + // Get input options + int rejectTypes = 0; + int dataFlags = 0; + int maxHits = 1; + bool detectPhantom = false; + for (int i = 0; i < options.Length; i += 2) + { + if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) + rejectTypes = options.GetLSLIntegerItem(i + 1); + else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) + dataFlags = options.GetLSLIntegerItem(i + 1); + else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) + maxHits = options.GetLSLIntegerItem(i + 1); + else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) + detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); + } + if (maxHits > m_maxHitsInCastRay) + maxHits = m_maxHitsInCastRay; + bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0); + bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0); + bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0); + bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0); + bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0); + bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0); + bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); + + // Calculate some basic parameters + Vector3 ray = end - start; + float rayLength = ray.Length(); + + // Try to get a mesher and return failure if none or degenerate ray + IRendering primMesher = null; + List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); + if (renderers.Count < 1 || rayLength < tol) + { + result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); + return result; + } + primMesher = RenderingLoader.LoadRenderer(renderers[0]); + + // Used to translate and rotate world so ray is along negative Z axis from origo and + // calculations mostly simplified to a 2D projecttion on the X-Y plane + Vector3 posProj = new Vector3(-start); + Quaternion rotProj = Vector3.RotationBetween(ray, new Vector3(0.0f, 0.0f, -1.0f)); + Quaternion rotBack = Quaternion.Inverse(rotProj); + + // Iterate over all objects/groups and prims/parts in region + World.ForEachSOG( + delegate(SceneObjectGroup group) + { + // Check group filters unless part filters are configured + bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); + bool isNonphysical = !isPhysical; + bool isPhantom = group.IsPhantom || group.IsVolumeDetect; + bool isAttachment = group.IsAttachment; + bool doGroup = true; + if (isPhysical && rejectPhysical) + doGroup = false; + if (isNonphysical && rejectNonphysical) + doGroup = false; + if (isPhantom && detectPhantom) + doGroup = true; + if (m_filterPartsInCastRay) + doGroup = true; + if (isAttachment && !m_doAttachmentsInCastRay) + doGroup = false; + // Parse object/group if passed filters + if (doGroup) + { + // Iterate over all prims/parts in object/group + foreach(SceneObjectPart part in group.Parts) + { + // Check part filters if configured + if (m_filterPartsInCastRay) + { + isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); + isNonphysical = !isPhysical; + isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); + bool doPart = true; + if (isPhysical && rejectPhysical) + doPart = false; + if (isNonphysical && rejectNonphysical) + doPart = false; + if (isPhantom && detectPhantom) + doPart = true; + if (!doPart) + continue; + } + // Parse prim/part if passed filters + + // Estimate bounding box from size box + Vector3 scaleSafe = part.Scale; + if (!part.Shape.SculptEntry) + scaleSafe = scaleSafe * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); + + // Filter parts by bounding shapes + Vector3 posPartRel = part.GetWorldPosition() + posProj; + Vector3 posPartProj = posPartRel * rotProj; + if (InBoundingShapes(ray, rayLength, scaleSafe, posPartRel, posPartProj, rotProj)) + { + // Prepare data needed to check for ray hits + RayTrans rayTrans = new RayTrans(); + rayTrans.PartId = part.UUID; + rayTrans.GroupId = part.ParentGroup.UUID; + rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; + rayTrans.Scale = part.Scale; + rayTrans.PositionPartProj = posPartProj; + rayTrans.PositionProj = posProj; + rayTrans.RotationPartProj = rotProj * part.GetWorldRotation(); + rayTrans.RotationBack = rotBack; + rayTrans.NeedsEnds = true; + rayTrans.RayLength = rayLength; + rayTrans.Tolerance = tol; + rayTrans.Tolerance2 = tol2; + + // Make an OMV prim to be able to mesh part + Primitive omvPrim = part.Shape.ToOmvPrimitive(posPartProj, rayTrans.RotationPartProj); + byte[] sculptAsset = null; + if (omvPrim.Sculpt != null) + sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + + // When part is mesh, get and check mesh + if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) + { + AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); + FacetedMesh mesh = null; + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); + meshAsset = null; + AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); + mesh = null; + } + + // When part is sculpt, create and check mesh + // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. + else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) + { + IJ2KDecoder imgDecoder = World.RequestModuleInterface(); + if (imgDecoder != null) + { + Image sculpt = imgDecoder.DecodeToImage(sculptAsset); + if (sculpt != null) + { + SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); + sculpt.Dispose(); + AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); + mesh = null; + } + } + } + + // When part is prim, create and check mesh + else if (omvPrim.Sculpt == null) + { + if ( + omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && + omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && + omvPrim.PrimData.PathSkew == 0.0 && + omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 + ) + rayTrans.NeedsEnds = false; + SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); + AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); + mesh = null; + } + + } + } + } + } + ); + + // Check avatar filter + if (!rejectAgents) + { + // Iterate over all avatars in region + World.ForEachRootScenePresence( + delegate (ScenePresence sp) + { + // Parse avatar + + // Get bounding box + Vector3 lower; + Vector3 upper; + BoundingBoxOfScenePresence(sp, out lower, out upper); + Vector3 scale = upper - lower; + + // Filter avatars by bounding shapes + Vector3 posPartRel = sp.AbsolutePosition + posProj + (lower + upper) * 0.5f * sp.Rotation; + Vector3 posPartProj = posPartRel * rotProj; + if (InBoundingShapes(ray, rayLength, scale, posPartRel, posPartProj, rotProj)) + { + // Prepare data needed to check for ray hits + RayTrans rayTrans = new RayTrans(); + rayTrans.PartId = sp.UUID; + rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; + rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; + rayTrans.Scale = scale; + rayTrans.PositionPartProj = posPartProj; + rayTrans.PositionProj = posProj; + rayTrans.RotationPartProj = rotProj * sp.Rotation; + rayTrans.RotationBack = rotBack; + rayTrans.NeedsEnds = false; + rayTrans.RayLength = rayLength; + rayTrans.Tolerance = tol; + rayTrans.Tolerance2 = tol2; + + // Make OMV prim, create and check mesh + Primitive omvPrim = MakeOpenMetaversePrim(scale, posPartProj, rayTrans.RotationPartProj, ScriptBaseClass.PRIM_TYPE_SPHERE); + SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); + AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); + mesh = null; + } + } + ); + } + + // Check terrain filter + if (!rejectLand) + { + // Parse terrain + + // Mesh terrain and check projected bounding box + Vector3 posPartProj = posProj * rotProj; + Quaternion rotPartProj = rotProj; + Vector3 lower; + Vector3 upper; + List triangles = TrisFromHeightmapUnderRay(start, end, out lower, out upper); + Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); + Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); + int dummy = 0; + AddBoundingBoxOfSimpleBox(lower, upper, posPartProj, rotPartProj, true, ref lowerBox, ref upperBox, ref dummy); + if (lowerBox.X <= tol && lowerBox.Y <= tol && lowerBox.Z <= tol && upperBox.X >= -tol && upperBox.Y >= -tol && upperBox.Z >= -rayLength - tol) + { + // Prepare data needed to check for ray hits + RayTrans rayTrans = new RayTrans(); + rayTrans.PartId = UUID.Zero; + rayTrans.GroupId = UUID.Zero; + rayTrans.Link = 0; + rayTrans.Scale = new Vector3 (1.0f, 1.0f, 1.0f); + rayTrans.PositionPartProj = posPartProj; + rayTrans.PositionProj = posProj; + rayTrans.RotationPartProj = rotPartProj; + rayTrans.RotationBack = rotBack; + rayTrans.NeedsEnds = true; + rayTrans.RayLength = rayLength; + rayTrans.Tolerance = tol; + rayTrans.Tolerance2 = tol2; + + // Check mesh + AddRayInTris(triangles, rayTrans, ref rayHits); + triangles = null; + } + } + + // Sort hits by ascending distance + rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance)); + + // Check excess hits per part and group + for (int t = 0; t < 2; t++) + { + int maxHitsPerType = 0; + UUID id = UUID.Zero; + if (t == 0) + maxHitsPerType = m_maxHitsPerPrimInCastRay; + else + maxHitsPerType = m_maxHitsPerObjectInCastRay; + + // Handle excess hits only when needed + if (maxHitsPerType < m_maxHitsInCastRay) + { + // Find excess hits + Hashtable hits = new Hashtable(); + for (int i = rayHits.Count - 1; i >= 0; i--) + { + if (t == 0) + id = rayHits[i].PartId; + else + id = rayHits[i].GroupId; + if (hits.ContainsKey(id)) + hits[id] = (int)hits[id] + 1; + else + hits[id] = 1; + } + + // Remove excess hits + for (int i = rayHits.Count - 1; i >= 0; i--) + { + if (t == 0) + id = rayHits[i].PartId; + else + id = rayHits[i].GroupId; + int hit = (int)hits[id]; + if (hit > m_maxHitsPerPrimInCastRay) + { + rayHits.RemoveAt(i); + hit--; + hits[id] = hit; + } + } + } + } + + // Parse hits into result list according to data flags + int hitCount = rayHits.Count; + if (hitCount > maxHits) + hitCount = maxHits; + for (int i = 0; i < hitCount; i++) + { + RayHit rayHit = rayHits[i]; + if (getRootKey) + result.Add(new LSL_Key(rayHit.GroupId.ToString())); + else + result.Add(new LSL_Key(rayHit.PartId.ToString())); + result.Add(new LSL_Vector(rayHit.Position)); + if (getLinkNum) + result.Add(new LSL_Integer(rayHit.Link)); + if (getNormal) + result.Add(new LSL_Vector(rayHit.Normal)); + } + result.Add(new LSL_Integer(hitCount)); + return result; + } + + /// + /// Struct for transmitting parameters required for finding llCastRay ray hits. + /// + public struct RayTrans + { + public UUID PartId; + public UUID GroupId; + public int Link; + public Vector3 Scale; + public Vector3 PositionPartProj; + public Vector3 PositionProj; + public Quaternion RotationPartProj; + public Quaternion RotationBack; + public bool NeedsEnds; + public float RayLength; + public float Tolerance; + public float Tolerance2; + } + + /// + /// Struct for llCastRay ray hits. + /// + public struct RayHit + { + public UUID PartId; + public UUID GroupId; + public int Link; + public Vector3 Position; + public Vector3 Normal; + public float Distance; + } + + /// + /// Helper to parse SimpleMesh for ray hits. + /// + private void AddRayInSimpleMesh(SimpleMesh mesh, RayTrans rayTrans, ref List rayHits) + { + if (mesh != null) + { + for (int i = 0; i < mesh.Indices.Count; i += 3) + { + Tri triangle = new Tri(); + triangle.p1 = mesh.Vertices[mesh.Indices[i]].Position; + triangle.p2 = mesh.Vertices[mesh.Indices[i + 1]].Position; + triangle.p3 = mesh.Vertices[mesh.Indices[i + 2]].Position; + AddRayInTri(triangle, rayTrans, ref rayHits); + } + } + } + + /// + /// Helper to parse FacetedMesh for ray hits. + /// + private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List rayHits) + { + if (mesh != null) + { + foreach (Face face in mesh.Faces) + { + for (int i = 0; i + /// Helper to parse Tri (triangle) List for ray hits. + /// + private void AddRayInTris(List triangles, RayTrans rayTrans, ref List rayHits) + { + foreach (Tri triangle in triangles) + { + AddRayInTri(triangle, rayTrans, ref rayHits); + } + } + + /// + /// Helper to add ray hit in a Tri (triangle). + /// + private void AddRayInTri(Tri triangle, RayTrans rayTrans, ref List rayHits) + { + // Check for hit in triangle + float distance; + Vector3 posHit; + Vector3 normal; + if (HitRayInTri(triangle, rayTrans, out distance, out posHit, out normal)) + { + // Project hit part back to normal coordinate system + Vector3 posPart = rayTrans.PositionPartProj * rayTrans.RotationBack - rayTrans.PositionProj; + // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) faces plane through shape center + if (Math.Abs(Vector3.Dot(posPart, normal) - Vector3.Dot(posHit, normal)) < rayTrans.Tolerance && !rayTrans.NeedsEnds) + return; + // Remove duplicate hits at triangle edges and intersections + for (int i = rayHits.Count - 1; i >= 0; i--) + { + if (rayHits[i].PartId == rayTrans.PartId && Math.Abs(rayHits[i].Distance - distance) < rayTrans.Tolerance2) + return; + } + + // Build result data set + RayHit rayHit = new RayHit(); + rayHit.PartId = rayTrans.PartId; + rayHit.GroupId = rayTrans.GroupId; + rayHit.Link = rayTrans.Link; + rayHit.Position = posHit; + rayHit.Normal = normal; + rayHit.Distance = distance; + rayHits.Add(rayHit); + } + } + + /// + /// Helper to find ray hit in a Tri (triangle). + /// + private bool HitRayInTri(Tri triangle, RayTrans rayTrans, out float distance, out Vector3 posHit, out Vector3 normal) + { + // Initialize + distance = 0.0f; + posHit = Vector3.Zero; + normal = Vector3.Zero; + float tol = rayTrans.Tolerance; + + // Project triangle on X-Y plane + Vector3 pos1 = triangle.p1 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; + Vector3 pos2 = triangle.p2 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; + Vector3 pos3 = triangle.p3 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; + + // Check if ray/origo inside triangle bounding rectangle + Vector3 lower = Vector3.Min(pos1, Vector3.Min(pos2, pos3)); + Vector3 upper = Vector3.Max(pos1, Vector3.Max(pos2, pos3)); + if (lower.X > tol || lower.Y > tol || lower.Z > tol || upper.X < -tol || upper.Y < -tol || upper.Z < -rayTrans.RayLength - tol) + return false; + + // Check if ray/origo inside every edge or reverse "outside" every edge on exit + float dist; + bool inside = true; + bool outside = true; + Vector3 vec1 = pos2 - pos1; + dist = pos1.X * vec1.Y - pos1.Y * vec1.X; + if (dist < -tol) + inside = false; + if (dist > tol) + outside = false; + Vector3 vec2 = pos3 - pos2; + dist = pos2.X * vec2.Y - pos2.Y * vec2.X; + if (dist < -tol) + inside = false; + if (dist > tol) + outside = false; + Vector3 vec3 = pos1 - pos3; + dist = pos3.X * vec3.Y - pos3.Y * vec3.X; + if (dist < -tol) + inside = false; + if (dist > tol) + outside = false; + + // Skip if ray/origo outside + if (!inside && !(outside && m_detectExitsInCastRay)) + return false; + + // Calculate normal + Vector3 normalProj = Vector3.Cross(vec1, vec2); + float normalLength = normalProj.Length(); + // Skip if degenerate triangle + if (normalLength < tol) + return false; + normalProj = normalProj / normalLength; + // Skip if ray parallell to triangle plane + if (Math.Abs(normalProj.Z) < tol) + return false; + + // Calculate distance + distance = Vector3.Dot(normalProj, pos2) / normalProj.Z * -1.0f; + // Skip if outside ray + if (distance < -tol || distance > rayTrans.RayLength + tol) + return false; + + // Calculate projected hit position + Vector3 posHitProj = new Vector3(0.0f, 0.0f, -distance); + // Project hit back to normal coordinate system + posHit = posHitProj * rayTrans.RotationBack - rayTrans.PositionProj; + normal = normalProj * rayTrans.RotationBack; + return true; + } + + /// + /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box. + /// + private List TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper) + { + // Get bounding X-Y rectangle of terrain under ray + lower = Vector3.Min(posStart, posEnd); + upper = Vector3.Max(posStart, posEnd); + lower.X = (float)Math.Floor(lower.X); + lower.Y = (float)Math.Floor(lower.Y); + float zLower = float.MaxValue; + upper.X = (float)Math.Ceiling(upper.X); + upper.Y = (float)Math.Ceiling(upper.Y); + float zUpper = float.MinValue; + + // Initialize Tri (triangle) List + List triangles = new List(); + + // Set parsing lane direction to major ray X-Y axis + Vector3 vec = posEnd - posStart; + float xAbs = Math.Abs(vec.X); + float yAbs = Math.Abs(vec.Y); + bool bigX = true; + if (yAbs > xAbs) + { + bigX = false; + vec = vec / yAbs; + } + else if (xAbs > yAbs || xAbs > 0.0f) + vec = vec / xAbs; + else + vec = new Vector3(1.0f, 1.0f, 0.0f); + + // Simplify by start parsing in lower end of lane + if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f)) + { + Vector3 posTemp = posStart; + posStart = posEnd; + posEnd = posTemp; + vec = vec * -1.0f; + } + + // First 1x1 rectangle under ray + float xFloorOld = 0.0f; + float yFloorOld = 0.0f; + Vector3 pos = posStart; + float xFloor = (float)Math.Floor(pos.X); + float yFloor = (float)Math.Floor(pos.Y); + AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); + + // Parse every remaining 1x1 rectangle under ray + while (pos != posEnd) + { + // Next 1x1 rectangle under ray + xFloorOld = xFloor; + yFloorOld = yFloor; + pos = pos + vec; + + // Clip position to 1x1 rectangle border + xFloor = (float)Math.Floor(pos.X); + yFloor = (float)Math.Floor(pos.Y); + if (bigX && pos.X > xFloor) + { + pos.Y -= vec.Y * (pos.X - xFloor); + pos.X = xFloor; + } + else if (!bigX && pos.Y > yFloor) + { + pos.X -= vec.X * (pos.Y - yFloor); + pos.Y = yFloor; + } + + // Last 1x1 rectangle under ray + if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y)) + { + pos = posEnd; + xFloor = (float)Math.Floor(pos.X); + yFloor = (float)Math.Floor(pos.Y); + } + + // Add new 1x1 rectangle in lane + if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld)) + AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); + // Add last 1x1 rectangle in old lane at lane shift + if (bigX && yFloor != yFloorOld) + AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper); + if (!bigX && xFloor != xFloorOld) + AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper); + } + + // Finalize bounding box Z + lower.Z = zLower; + upper.Z = zUpper; + + // Done and returning Tri (triangle)List + return triangles; + } + + /// + /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box. + /// + private void AddTrisFromHeightmap(float xPos, float yPos, ref List triangles, ref float zLower, ref float zUpper) + { + int xInt = (int)xPos; + int yInt = (int)yPos; + + // Corner 1 of 1x1 rectangle + int x = Util.Clamp(xInt+1, 0, World.Heightmap.Width - 1); + int y = Util.Clamp(yInt+1, 0, World.Heightmap.Height - 1); + Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]); + // Adjust bounding box + zLower = Math.Min(zLower, pos1.Z); + zUpper = Math.Max(zUpper, pos1.Z); + + // Corner 2 of 1x1 rectangle + x = Util.Clamp(xInt, 0, World.Heightmap.Width - 1); + y = Util.Clamp(yInt+1, 0, World.Heightmap.Height - 1); + Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); + // Adjust bounding box + zLower = Math.Min(zLower, pos1.Z); + zUpper = Math.Max(zUpper, pos1.Z); + + // Corner 3 of 1x1 rectangle + x = Util.Clamp(xInt, 0, World.Heightmap.Width - 1); + y = Util.Clamp(yInt, 0, World.Heightmap.Height - 1); + Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); + // Adjust bounding box + zLower = Math.Min(zLower, pos1.Z); + zUpper = Math.Max(zUpper, pos1.Z); + + // Corner 4 of 1x1 rectangle + x = Util.Clamp(xInt+1, 0, World.Heightmap.Width - 1); + y = Util.Clamp(yInt, 0, World.Heightmap.Height - 1); + Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); + // Adjust bounding box + zLower = Math.Min(zLower, pos1.Z); + zUpper = Math.Max(zUpper, pos1.Z); + + // Add triangle 1 + Tri triangle1 = new Tri(); + triangle1.p1 = pos1; + triangle1.p2 = pos2; + triangle1.p3 = pos3; + triangles.Add(triangle1); + + // Add triangle 2 + Tri triangle2 = new Tri(); + triangle2.p1 = pos3; + triangle2.p2 = pos4; + triangle2.p3 = pos1; + triangles.Add(triangle2); + } + + /// + /// Helper to check if a ray intersects bounding shapes. + /// + private bool InBoundingShapes(Vector3 ray, float rayLength, Vector3 scale, Vector3 posPartRel, Vector3 posPartProj, Quaternion rotProj) + { + float tol = m_floatToleranceInCastRay; + + // Check if ray intersects projected bounding box + Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); + Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); + int dummy = 0; + AddBoundingBoxOfSimpleBox(scale * -0.5f, scale * 0.5f, posPartProj, rotProj, true, ref lowerBox, ref upperBox, ref dummy); + if (lowerBox.X > tol || lowerBox.Y > tol || lowerBox.Z > tol || upperBox.X < -tol || upperBox.Y < -tol || upperBox.Z < -rayLength - tol) + return false; + + // Passed bounding shape filters, so return true + return true; + } + + /// + /// Helper to get link number for a UUID. + /// + private int UUID2LinkNumber(SceneObjectPart part, UUID id) + { + SceneObjectGroup group = part.ParentGroup; + if (group != null) + { + // Parse every link for UUID + int linkCount = group.PrimCount + group.GetSittingAvatarsCount(); + for (int link = linkCount; link > 0; link--) + { + ISceneEntity entity = GetLinkEntity(part, link); + // Return link number if UUID match + if (entity != null && entity.UUID == id) + return link; + } + } + // Return link number 0 if no links or UUID matches + return 0; + } + public LSL_Integer llManageEstateAccess(int action, string avatar) { m_host.AddScriptLPS(1); -- cgit v1.1 From c96ee68953eb31fc2ad6d1df9b7a4bb19c584e17 Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Mon, 4 May 2015 10:51:04 +0200 Subject: Patch llCastRay fully-simplified to V2. Signed-off-by: Michael Cerquoni --- .../Shared/Api/Implementation/LSL_Api.cs | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cf1bd2b..58b3930 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -221,6 +221,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffX = 2.414214f; protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; + protected bool m_useCastRayV2 = false; + protected int RC_USE_V2 = 512; protected float m_floatToleranceInCastRay = 0.000001f; protected float m_floatTolerance2InCastRay = 0.0001f; protected int m_maxHitsInCastRay = 16; @@ -229,7 +231,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected bool m_detectExitsInCastRay = false; protected bool m_filterPartsInCastRay = false; protected bool m_doAttachmentsInCastRay = false; - protected bool m_useCastRayV1 = true; //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -336,6 +337,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); + m_useCastRayV2 = lslConfig.GetBoolean("UseLlCastRayV2", m_useCastRayV2); + RC_USE_V2 = lslConfig.GetInt("RC_USE_V2", RC_USE_V2); m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); @@ -344,7 +347,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); - m_useCastRayV1 = lslConfig.GetBoolean("UseLlCastRayV1", m_useCastRayV1); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -13763,7 +13765,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return contacts[0]; } - public LSL_List llCastRayV1(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) { LSL_List list = new LSL_List(); @@ -13792,6 +13794,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rejectTypes = options.GetLSLIntegerItem(i + 1); } + // Use llCastRay v2 if configured or requested + if (m_useCastRayV2 || (dataFlags & RC_USE_V2) == RC_USE_V2) + return llCastRayV2(start, end, options); + if (count > 16) count = 16; @@ -13955,25 +13961,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Full implementation of llCastRay similar to SL 2015-04-21. + /// Implementation of llCastRay similar to SL 2015-04-21. /// http://wiki.secondlife.com/wiki/LlCastRay /// Uses pure geometry, bounding shapes, meshing and no physics /// for prims, sculpts, meshes, avatars and terrain. /// Implements all flags, reject types and data flags. /// Can handle both objects/groups and prims/parts, by config. - /// May give poor results with multi-part meshes where "root" - /// part doesn't dominate, owing to "guessed" bounding boxes. /// May sometimes be inaccurate owing to calculation precision /// and a bug in libopenmetaverse PrimMesher. /// - public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRayV2(LSL_Vector start, LSL_Vector end, LSL_List options) { - // Use llCastRay v1 if configured - if (m_useCastRayV1) - return llCastRayV1(start, end, options); - // Initialize - m_host.AddScriptLPS(1); + // Keep AddScriptLPS commented while called from llCastRay + // m_host.AddScriptLPS(1); List rayHits = new List(); LSL_List result = new LSL_List(); float tol = m_floatToleranceInCastRay; @@ -14009,10 +14010,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Vector3 ray = end - start; float rayLength = ray.Length(); - // Try to get a mesher and return failure if none or degenerate ray + // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits IRendering primMesher = null; List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); - if (renderers.Count < 1 || rayLength < tol) + if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) { result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); return result; -- cgit v1.1 From 5a2440dfdf4a4ab769692330f6d4f98521e271ce Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Fri, 1 May 2015 07:00:45 +0200 Subject: Implement llGetGeometricCenter correctly. Signed-off-by: Michael Cerquoni --- .../Shared/Api/Implementation/LSL_Api.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 58b3930..2fcfcbe 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10087,9 +10087,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return prim; } + /// + /// Implementation of llGetGeometricCenter according to SL 2015-04-30. + /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter + /// Returns the average position offset of all linked parts, + /// including the root prim and seated avatars, + /// relative to the root prim in local coordinates. + /// public LSL_Vector llGetGeometricCenter() { - return new LSL_Vector(m_host.GetGeometricCenter()); + // Subtract whatever position the root prim has to make it zero + Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f; + + // Add all prim/part position offsets + foreach (SceneObjectPart part in m_host.ParentGroup.Parts) + offset = offset + part.OffsetPosition; + // Add all avatar/scene presence position offsets + foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars()) + offset = offset + sp.OffsetPosition; + + // Calculate and return the average offset + offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount()); + return new LSL_Vector(offset); } public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) -- cgit v1.1 From 382e05df143a2434a855d097c764fb7cbac16ceb Mon Sep 17 00:00:00 2001 From: Talun Date: Thu, 30 Apr 2015 21:39:11 +0100 Subject: Missing constants for llGetObjectDetails OBJECT_BODY_SHAPE_TYPE OBJECT_HOVER_HEIGHT OBJECT_LAST_OWNER_ID OBJECT_RENDER_WEIGHT Signed-off-by: Michael Cerquoni --- .../Shared/Api/Implementation/LSL_Api.cs | 29 ++++++++++++++++++++++ .../Shared/Api/Runtime/LSL_Constants.cs | 4 +++ 2 files changed, 33 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2fcfcbe..25f1958 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -13051,6 +13051,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.OBJECT_TEMP_ON_REZ: ret.Add(new LSL_Integer(0)); break; + case ScriptBaseClass.OBJECT_RENDER_WEIGHT: + ret.Add(new LSL_Integer(-1)); + break; + case ScriptBaseClass.OBJECT_HOVER_HEIGHT: + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: + LSL_Float shapeType; + if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0) + shapeType = new LSL_Float(1); + else + shapeType = new LSL_Float(0); + ret.Add(shapeType); + break; + case ScriptBaseClass.OBJECT_LAST_OWNER_ID: + ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY)); + break; default: // Invalid or unhandled constant. ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); @@ -13215,6 +13232,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.OBJECT_TEMP_ON_REZ: ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); break; + case ScriptBaseClass.OBJECT_RENDER_WEIGHT: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_HOVER_HEIGHT: + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: + ret.Add(new LSL_Float(-1)); + break; + case ScriptBaseClass.OBJECT_LAST_OWNER_ID: + ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString())); + break; default: // Invalid or unhandled constant. ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index a96cd16..e37d3af 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -596,6 +596,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int OBJECT_PHYSICS = 21; public const int OBJECT_PHANTOM = 22; public const int OBJECT_TEMP_ON_REZ = 23; + public const int OBJECT_RENDER_WEIGHT = 24; + public const int OBJECT_HOVER_HEIGHT = 25; + public const int OBJECT_BODY_SHAPE_TYPE = 26; + public const int OBJECT_LAST_OWNER_ID = 27; // Pathfinding types public const int OPT_OTHER = -1; -- cgit v1.1 From 49991d055a889f2bd082695383b664a40107db40 Mon Sep 17 00:00:00 2001 From: H-H-H Date: Fri, 1 May 2015 19:30:56 +0100 Subject: Adding the command to opensim console which requires a region name as an argument and will do an oar of that region if the autobackup module is enabled Signed-off-by: Michael Cerquoni --- .../World/AutoBackup/AutoBackupModule.cs | 42 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index 28dc5f5..c17a368 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -115,6 +115,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup private delegate T DefaultGetter(string settingName, T defaultValue); private bool m_enabled; + private ICommandConsole m_console; + private List m_Scenes = new List (); + /// /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! @@ -206,8 +209,20 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. /// /// - void IRegionModuleBase.AddRegion(Scene scene) + void IRegionModuleBase.AddRegion (Scene scene) { + if (!this.m_enabled) { + return; + } + lock (m_Scenes) { + m_Scenes.Add (scene); + } + m_console = MainConsole.Instance; + + m_console.Commands.AddCommand ( + "AutoBackup", false, "dobackup", + "dobackup", + "do backup.", DoBackup); } /// @@ -220,7 +235,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup { return; } - + m_Scenes.Remove (scene); if (this.m_states.ContainsKey(scene)) { AutoBackupModuleState abms = this.m_states[scene]; @@ -275,6 +290,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup #endregion + + private void DoBackup (string module, string[] args) + { + if (args.Length != 2) { + MainConsole.Instance.OutputFormat ("Usage: dobackup "); + return; + } + bool found = false; + string name = args [1]; + lock (m_Scenes) { + foreach (Scene s in m_Scenes) { + string test = s.Name.ToString (); + if (test == name) { + found = true; + DoRegionBackup (s); + } + } + if (!found) { + MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name); + } + } + } + /// /// Set up internal state for a given scene. Fairly complex code. /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene. -- cgit v1.1 From dfb73c1464b981c158661bc443d7323f4928d2b9 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni Date: Mon, 4 May 2015 15:56:12 -0400 Subject: fix a minor whitespace issue --- OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index c17a368..ceb3332 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -290,7 +290,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup #endregion - private void DoBackup (string module, string[] args) { if (args.Length != 2) { -- cgit v1.1 From 44b8b9fef625f6f562a7d8cb0531bd518f11d037 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni Date: Mon, 4 May 2015 16:23:16 -0400 Subject: Revert "Patch llCastRay fully-simplified to V2." for further review. This reverts commit c96ee68953eb31fc2ad6d1df9b7a4bb19c584e17. --- .../Shared/Api/Implementation/LSL_Api.cs | 29 +++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 25f1958..c90f015 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -221,8 +221,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffX = 2.414214f; protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; - protected bool m_useCastRayV2 = false; - protected int RC_USE_V2 = 512; protected float m_floatToleranceInCastRay = 0.000001f; protected float m_floatTolerance2InCastRay = 0.0001f; protected int m_maxHitsInCastRay = 16; @@ -231,6 +229,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected bool m_detectExitsInCastRay = false; protected bool m_filterPartsInCastRay = false; protected bool m_doAttachmentsInCastRay = false; + protected bool m_useCastRayV1 = true; //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -337,8 +336,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); - m_useCastRayV2 = lslConfig.GetBoolean("UseLlCastRayV2", m_useCastRayV2); - RC_USE_V2 = lslConfig.GetInt("RC_USE_V2", RC_USE_V2); m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); @@ -347,6 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); + m_useCastRayV1 = lslConfig.GetBoolean("UseLlCastRayV1", m_useCastRayV1); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -13813,7 +13811,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return contacts[0]; } - public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRayV1(LSL_Vector start, LSL_Vector end, LSL_List options) { LSL_List list = new LSL_List(); @@ -13842,10 +13840,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api rejectTypes = options.GetLSLIntegerItem(i + 1); } - // Use llCastRay v2 if configured or requested - if (m_useCastRayV2 || (dataFlags & RC_USE_V2) == RC_USE_V2) - return llCastRayV2(start, end, options); - if (count > 16) count = 16; @@ -14009,20 +14003,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Implementation of llCastRay similar to SL 2015-04-21. + /// Full implementation of llCastRay similar to SL 2015-04-21. /// http://wiki.secondlife.com/wiki/LlCastRay /// Uses pure geometry, bounding shapes, meshing and no physics /// for prims, sculpts, meshes, avatars and terrain. /// Implements all flags, reject types and data flags. /// Can handle both objects/groups and prims/parts, by config. + /// May give poor results with multi-part meshes where "root" + /// part doesn't dominate, owing to "guessed" bounding boxes. /// May sometimes be inaccurate owing to calculation precision /// and a bug in libopenmetaverse PrimMesher. /// - public LSL_List llCastRayV2(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) { + // Use llCastRay v1 if configured + if (m_useCastRayV1) + return llCastRayV1(start, end, options); + // Initialize - // Keep AddScriptLPS commented while called from llCastRay - // m_host.AddScriptLPS(1); + m_host.AddScriptLPS(1); List rayHits = new List(); LSL_List result = new LSL_List(); float tol = m_floatToleranceInCastRay; @@ -14058,10 +14057,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Vector3 ray = end - start; float rayLength = ray.Length(); - // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits + // Try to get a mesher and return failure if none or degenerate ray IRendering primMesher = null; List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); - if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) + if (renderers.Count < 1 || rayLength < tol) { result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); return result; -- cgit v1.1 From 1abbad71b4603245e5481c11e3ce55f57b64935f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 5 May 2015 20:59:09 -0700 Subject: Refactored some code that is used in two different dlls related to SOP rewriting. Also added some unit tests that relate to mantis #7514 --- .../External/ExternalRepresentationUtils.cs | 184 +++++++++++++++++- .../Framework/InventoryAccess/HGAssetMapper.cs | 209 +-------------------- .../CoreModules/World/Archiver/AssetsRequest.cs | 2 +- .../Scenes/Tests/SceneObjectSerializationTests.cs | 136 ++++++++++++++ .../Services/HypergridService/HGAssetService.cs | 2 +- 5 files changed, 323 insertions(+), 210 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index 6debf65..64de18b 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs @@ -125,7 +125,8 @@ namespace OpenSim.Framework.Serialization.External /// The service for retrieving user account information /// The scope of the user account information (Grid ID) /// The SceneObjectPart represented in XML2 - public static string RewriteSOP(string xml, string homeURL, IUserAccountService userService, UUID scopeID) + [Obsolete("This method is deprecated. Use RewriteSOP instead.")] + public static string RewriteSOP_Old(string xml, string homeURL, IUserAccountService userService, UUID scopeID) { if (xml == string.Empty || homeURL == string.Empty || userService == null) return xml; @@ -173,6 +174,187 @@ namespace OpenSim.Framework.Serialization.External } } + /// + /// Takes a XML representation of a SceneObjectPart and returns another XML representation + /// with creator data added to it. + /// + /// The SceneObjectPart represented in XML2 + /// An identifier for the component that's calling this function + /// The URL of the user agents service (home) for the creator + /// The service for retrieving user account information + /// The scope of the user account information (Grid ID) + /// The SceneObjectPart represented in XML2 + public static string RewriteSOP(string xmlData, string sceneName, string homeURL, IUserAccountService userService, UUID scopeID) + { + // Console.WriteLine("Input XML [{0}]", xmlData); + if (xmlData == string.Empty || homeURL == string.Empty || userService == null) + return xmlData; + + using (StringWriter sw = new StringWriter()) + using (XmlTextWriter writer = new XmlTextWriter(sw)) + using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) + using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) + { + TransformXml(reader, writer, sceneName, homeURL, userService, scopeID); + + // Console.WriteLine("Output: [{0}]", sw.ToString()); + + return sw.ToString(); + } + } + + protected static void TransformXml(XmlReader reader, XmlWriter writer, string sceneName, string homeURI, IUserAccountService userAccountService, UUID scopeID) + { + // m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML"); + + int sopDepth = -1; + UserAccount creator = null; + bool hasCreatorData = false; + + while (reader.Read()) + { + // Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name); + + switch (reader.NodeType) + { + case XmlNodeType.Attribute: + // Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name); + writer.WriteAttributeString(reader.Name, reader.Value); + break; + + case XmlNodeType.CDATA: + writer.WriteCData(reader.Value); + break; + + case XmlNodeType.Comment: + writer.WriteComment(reader.Value); + break; + + case XmlNodeType.DocumentType: + writer.WriteDocType(reader.Name, reader.Value, null, null); + break; + + case XmlNodeType.Element: + // m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name); + + writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); + + if (reader.HasAttributes) + { + while (reader.MoveToNextAttribute()) + writer.WriteAttributeString(reader.Name, reader.Value); + + reader.MoveToElement(); + } + + if (reader.LocalName == "SceneObjectPart") + { + if (sopDepth < 0) + { + sopDepth = reader.Depth; + // m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth); + } + } + else + { + if (sopDepth >= 0 && reader.Depth == sopDepth + 1) + { + if (reader.Name == "CreatorID") + { + reader.Read(); + if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID") + { + reader.Read(); + + if (reader.NodeType == XmlNodeType.Text) + { + UUID uuid = UUID.Zero; + UUID.TryParse(reader.Value, out uuid); + creator = userAccountService.GetUserAccount(scopeID, uuid); + writer.WriteElementString("UUID", reader.Value); + reader.Read(); + } + else + { + // If we unexpected run across mixed content in this node, still carry on + // transforming the subtree (this replicates earlier behaviour). + TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID); + } + } + else + { + // If we unexpected run across mixed content in this node, still carry on + // transforming the subtree (this replicates earlier behaviour). + TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID); + } + } + else if (reader.Name == "CreatorData") + { + reader.Read(); + if (reader.NodeType == XmlNodeType.Text) + { + hasCreatorData = true; + writer.WriteString(reader.Value); + } + else + { + // If we unexpected run across mixed content in this node, still carry on + // transforming the subtree (this replicates earlier behaviour). + TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID); + } + } + } + } + + if (reader.IsEmptyElement) + { + // m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name); + writer.WriteEndElement(); + } + + break; + + case XmlNodeType.EndElement: + // m_log.DebugFormat("Depth {0} at EndElement", reader.Depth); + if (sopDepth == reader.Depth) + { + if (!hasCreatorData && creator != null) + writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", homeURI, creator.FirstName, creator.LastName)); + + // m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth"); + sopDepth = -1; + creator = null; + hasCreatorData = false; + } + writer.WriteEndElement(); + break; + + case XmlNodeType.EntityReference: + writer.WriteEntityRef(reader.Name); + break; + + case XmlNodeType.ProcessingInstruction: + writer.WriteProcessingInstruction(reader.Name, reader.Value); + break; + + case XmlNodeType.Text: + writer.WriteString(reader.Value); + break; + + case XmlNodeType.XmlDeclaration: + // For various reasons, not all serializations have xml declarations (or consistent ones) + // and as it's embedded inside a byte stream we don't need it anyway, so ignore. + break; + + default: + m_log.WarnFormat( + "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}", + reader.NodeType, sceneName); + break; + } + } + } + public static string CalcCreatorData(string homeURL, string name) { return homeURL + ";" + name; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index c2010b1..f54298c 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -35,6 +35,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Serialization.External; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; @@ -189,217 +190,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return Utils.StringToBytes(RewriteSOP(xml)); } - protected void TransformXml(XmlReader reader, XmlWriter writer) - { -// m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML"); - - int sopDepth = -1; - UserAccount creator = null; - bool hasCreatorData = false; - - while (reader.Read()) - { -// Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name); - - switch (reader.NodeType) - { - case XmlNodeType.Attribute: -// Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name); - writer.WriteAttributeString(reader.Name, reader.Value); - break; - - case XmlNodeType.CDATA: - writer.WriteCData(reader.Value); - break; - - case XmlNodeType.Comment: - writer.WriteComment(reader.Value); - break; - - case XmlNodeType.DocumentType: - writer.WriteDocType(reader.Name, reader.Value, null, null); - break; - - case XmlNodeType.Element: -// m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name); - - writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); - - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - writer.WriteAttributeString(reader.Name, reader.Value); - - reader.MoveToElement(); - } - - if (reader.LocalName == "SceneObjectPart") - { - if (sopDepth < 0) - { - sopDepth = reader.Depth; -// m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth); - } - } - else - { - if (sopDepth >= 0 && reader.Depth == sopDepth + 1) - { - if (reader.Name == "CreatorID") - { - reader.Read(); - if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID") - { - reader.Read(); - - if (reader.NodeType == XmlNodeType.Text) - { - UUID uuid = UUID.Zero; - UUID.TryParse(reader.Value, out uuid); - creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); - writer.WriteElementString("UUID", reader.Value); - reader.Read(); - } - else - { - // If we unexpected run across mixed content in this node, still carry on - // transforming the subtree (this replicates earlier behaviour). - TransformXml(reader, writer); - } - } - else - { - // If we unexpected run across mixed content in this node, still carry on - // transforming the subtree (this replicates earlier behaviour). - TransformXml(reader, writer); - } - } - else if (reader.Name == "CreatorData") - { - reader.Read(); - if (reader.NodeType == XmlNodeType.Text) - { - hasCreatorData = true; - writer.WriteString(reader.Value); - } - else - { - // If we unexpected run across mixed content in this node, still carry on - // transforming the subtree (this replicates earlier behaviour). - TransformXml(reader, writer); - } - } - } - } - - if (reader.IsEmptyElement) - { -// m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name); - writer.WriteEndElement(); - } - - break; - - case XmlNodeType.EndElement: -// m_log.DebugFormat("Depth {0} at EndElement", reader.Depth); - if (sopDepth == reader.Depth) - { - if (!hasCreatorData && creator != null) - writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", m_HomeURI, creator.FirstName, creator.LastName)); - -// m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth"); - sopDepth = -1; - creator = null; - hasCreatorData = false; - } - writer.WriteEndElement(); - break; - - case XmlNodeType.EntityReference: - writer.WriteEntityRef(reader.Name); - break; - - case XmlNodeType.ProcessingInstruction: - writer.WriteProcessingInstruction(reader.Name, reader.Value); - break; - - case XmlNodeType.Text: - writer.WriteString(reader.Value); - break; - - case XmlNodeType.XmlDeclaration: - // For various reasons, not all serializations have xml declarations (or consistent ones) - // and as it's embedded inside a byte stream we don't need it anyway, so ignore. - break; - - default: - m_log.WarnFormat( - "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}", - reader.NodeType, m_scene.Name); - break; - } - } - } - protected string RewriteSOP(string xmlData) { // Console.WriteLine("Input XML [{0}]", xmlData); + return ExternalRepresentationUtils.RewriteSOP(xmlData, m_scene.Name, m_HomeURI, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID); - using (StringWriter sw = new StringWriter()) - using (XmlTextWriter writer = new XmlTextWriter(sw)) - using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) - using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) - { - TransformXml(reader, writer); - -// Console.WriteLine("Output: [{0}]", sw.ToString()); - - return sw.ToString(); - } - - // We are now taking the more complex streaming approach above because some assets can be very large - // and can trigger higher CPU use or possibly memory problems. -// XmlDocument doc = new XmlDocument(); -// doc.LoadXml(xml); -// XmlNodeList sops = doc.GetElementsByTagName("SceneObjectPart"); -// -// foreach (XmlNode sop in sops) -// { -// UserAccount creator = null; -// bool hasCreatorData = false; -// XmlNodeList nodes = sop.ChildNodes; -// foreach (XmlNode node in nodes) -// { -// if (node.Name == "CreatorID") -// { -// UUID uuid = UUID.Zero; -// UUID.TryParse(node.InnerText, out uuid); -// creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); -// } -// if (node.Name == "CreatorData" && node.InnerText != null && node.InnerText != string.Empty) -// hasCreatorData = true; -// -// //if (node.Name == "OwnerID") -// //{ -// // UserAccount owner = GetUser(node.InnerText); -// // if (owner != null) -// // node.InnerText = m_ProfileServiceURL + "/" + node.InnerText + "/" + owner.FirstName + " " + owner.LastName; -// //} -// } -// -// if (!hasCreatorData && creator != null) -// { -// XmlElement creatorData = doc.CreateElement("CreatorData"); -// creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName; -// sop.AppendChild(creatorData); -// } -// } -// -// using (StringWriter wr = new StringWriter()) -// { -// doc.Save(wr); -// return wr.ToString(); -// } } // TODO: unused diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 4d99a6e..db66c83 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -335,7 +335,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) { //m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID); - string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), m_options["home"].ToString(), m_userAccountService, m_scopeID); + string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), string.Empty, m_options["home"].ToString(), m_userAccountService, m_scopeID); asset.Data = Utils.StringToBytes(xml); } return asset; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs new file mode 100644 index 0000000..927d8e8 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs @@ -0,0 +1,136 @@ +/* + * 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 System.Collections.Generic; +using System.Reflection; +using System.Threading; +using System.Xml; +using System.Linq; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Serialization.External; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Basic scene object serialization tests. + /// + [TestFixture] + public class SceneObjectSerializationTests : OpenSimTestCase + { + + /// + /// Serialize and deserialize. + /// + [Test] + public void TestSerialDeserial() + { + TestHelpers.InMethod(); + + Scene scene = new SceneHelpers().SetupScene(); + int partsToTestCount = 3; + + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); + SceneObjectPart[] parts = so.Parts; + so.Name = "obj1"; + so.Description = "xpto"; + + string xml = SceneObjectSerializer.ToXml2Format(so); + Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string"); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart"); + Assert.That(nodes.Count, Is.EqualTo(3), "SOG serialization resulted in wrong number of SOPs"); + + SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml); + Assert.IsNotNull(so2, "SOG deserialization resulted in null object"); + Assert.That(so2.Name == so.Name, "Name of deserialized object does not match original name"); + Assert.That(so2.Description == so.Description, "Description of deserialized object does not match original name"); + } + + /// + /// This checks for a bug reported in mantis #7514 + /// + [Test] + public void TestNamespaceAttribute() + { + TestHelpers.InMethod(); + + Scene scene = new SceneHelpers().SetupScene(); + UserAccount account = new UserAccount(UUID.Zero, UUID.Random(), "Test", "User", string.Empty); + scene.UserAccountService.StoreUserAccount(account); + int partsToTestCount = 1; + + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); + SceneObjectPart[] parts = so.Parts; + so.Name = "obj1"; + so.Description = "xpto"; + so.OwnerID = account.PrincipalID; + so.RootPart.CreatorID = so.OwnerID; + + string xml = SceneObjectSerializer.ToXml2Format(so); + Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string"); + + xml = ExternalRepresentationUtils.RewriteSOP(xml, "Test Scene", "http://localhost", scene.UserAccountService, UUID.Zero); + //Console.WriteLine(xml); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart"); + Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no SOPs"); + foreach (XmlAttribute a in nodes[0].Attributes) + { + int count = a.Name.Count(c => c == ':'); + Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in SOP"); + } + nodes = doc.GetElementsByTagName("CreatorData"); + Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no CreatorData"); + foreach (XmlAttribute a in nodes[0].Attributes) + { + int count = a.Name.Count(c => c == ':'); + Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in CreatorData"); + } + + SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml); + Assert.IsNotNull(so2, "SOG deserialization resulted in null object"); + Assert.AreNotEqual(so.RootPart.CreatorIdentification, so2.RootPart.CreatorIdentification, "RewriteSOP failed to transform CreatorData."); + Assert.That(so2.RootPart.CreatorIdentification.Contains("http://"), "RewriteSOP failed to add the homeURL to CreatorData"); + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs index b57f8d8..a829932 100644 --- a/OpenSim/Services/HypergridService/HGAssetService.cs +++ b/OpenSim/Services/HypergridService/HGAssetService.cs @@ -163,7 +163,7 @@ namespace OpenSim.Services.HypergridService protected byte[] AdjustIdentifiers(byte[] data) { string xml = Utils.BytesToString(data); - return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_HomeURL, m_Cache, UUID.Zero)); + return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, "HGAssetService", m_HomeURL, m_Cache, UUID.Zero)); } } -- cgit v1.1 From 8676b017b24009cc26b274d211d43890594551c1 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 5 May 2015 21:28:27 -0700 Subject: Attempt at fixing mantis #7054. The two inventory threads are stepping on each other's feet. This needs real-world testing, as I'm not sure of all the consequences of reducing the number of worker threads to 1. --- OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 053a6a2..e402b0b 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -201,11 +201,12 @@ namespace OpenSim.Region.ClientStack.Linden Scene.EventManager.OnRegisterCaps += RegisterCaps; + int nworkers = 1; // was 2 if (ProcessQueuedRequestsAsync && m_workerThreads == null) { - m_workerThreads = new Thread[2]; + m_workerThreads = new Thread[nworkers]; - for (uint i = 0; i < 2; i++) + for (uint i = 0; i < nworkers; i++) { m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests, String.Format("InventoryWorkerThread{0}", i), -- cgit v1.1 From 4bf62e11b6a99c024e3dfa42db7425ea790009ee Mon Sep 17 00:00:00 2001 From: Dev Random Date: Wed, 6 May 2015 13:15:41 -0400 Subject: 'terrain modify' command for area-of-effect operations Signed-off-by: Michael Cerquoni --- .../CoreModules/World/Terrain/ITerrainModifier.cs | 77 +++++ .../World/Terrain/Modifiers/FillModifier.cs | 94 +++++ .../World/Terrain/Modifiers/LowerModifier.cs | 93 +++++ .../World/Terrain/Modifiers/MaxModifier.cs | 93 +++++ .../World/Terrain/Modifiers/MinModifier.cs | 93 +++++ .../World/Terrain/Modifiers/RaiseModifier.cs | 93 +++++ .../World/Terrain/Modifiers/SmoothModifier.cs | 132 +++++++ .../CoreModules/World/Terrain/TerrainModifier.cs | 378 +++++++++++++++++++++ .../World/Terrain/TerrainModifierData.cs | 17 + .../CoreModules/World/Terrain/TerrainModule.cs | 339 ++++++++++-------- 10 files changed, 1266 insertions(+), 143 deletions(-) create mode 100644 OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs new file mode 100644 index 0000000..0e0a0e4 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs @@ -0,0 +1,77 @@ +/* + * 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.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public interface ITerrainModifier + { + /// + /// Creates the feature. + /// + /// + /// Empty string if successful, otherwise error message. + /// + /// + /// ITerrainChannel holding terrain data. + /// + /// + /// command-line arguments from console. + /// + string ModifyTerrain(ITerrainChannel map, string[] args); + + /// + /// Gets a string describing the usage. + /// + /// + /// A string describing parameters for creating the feature. + /// Format is "feature-name ..." + /// + string GetUsage(); + + /// + /// Apply the appropriate operation on the specified map, at (x, y). + /// + /// + /// Map. + /// + /// + /// Data. + /// + /// + /// X. + /// + /// + /// Y. + /// + double operate(double[,] map, TerrainModifierData data, int x, int y); + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs new file mode 100644 index 0000000..0df7132 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs @@ -0,0 +1,94 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class FillModifier : TerrainModifier + { + + public FillModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "fill [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nSets all points within the specified range to the specified value."; + return val; + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double factor = this.computeBevel(data, x, y); + double result = data.elevation - (data.elevation - data.bevelevation) * factor; + return result; + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs new file mode 100644 index 0000000..3e4a457 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs @@ -0,0 +1,93 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class LowerModifier : TerrainModifier + { + public LowerModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "lower [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nLowers all points within the specified range by the specified amount."; + return val; + + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double factor = this.computeBevel(data, x, y); + double result = map[x, y] - (data.elevation - (data.elevation - data.bevelevation) * factor); + return result; + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs new file mode 100644 index 0000000..02f1852 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs @@ -0,0 +1,93 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class MaxModifier : TerrainModifier + { + public MaxModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "max [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nEnsures that all points within the specified range are no higher than the specified value."; + return val; + + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double factor = this.computeBevel(data, x, y); + double result = Math.Min(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]); + return result; + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs new file mode 100644 index 0000000..2db49c8 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs @@ -0,0 +1,93 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class MinModifier : TerrainModifier + { + public MinModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "min [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nEnsures that all points within the specified range are no lower than the specified value."; + return val; + + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double factor = this.computeBevel(data, x, y); + double result = Math.Max(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]); + return result; + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs new file mode 100644 index 0000000..9ac1edd --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs @@ -0,0 +1,93 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class RaiseModifier : TerrainModifier + { + public RaiseModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "raise [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nRaises all points within the specified range by the specified amount."; + return val; + + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double factor = this.computeBevel(data, x, y); + double result = map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor); + return result; + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs new file mode 100644 index 0000000..1731cd8 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs @@ -0,0 +1,132 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class SmoothModifier : TerrainModifier + { + public SmoothModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.bevel == "taper") + { + if (data.bevelevation < 0.01 || data.bevelevation > 0.99) + { + result = String.Format("Taper must be 0.01 to 0.99 {0}", data.bevelevation); + } + } + else + { + data.bevelevation = 2.0f / 3.0f; + } + + if (data.elevation < 0.0 || data.elevation > 1.0) + { + result = String.Format("Scaling factor must be 0.0 to 1.0: {0}", data.elevation); + } + + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "smooth [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nSmooths all points within the specified range using a simple averaging algorithm."; + return val; + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double[] scale = new double[3]; + scale[0] = data.elevation; + scale[1] = ((1.0 - scale[0]) * data.bevelevation) / 8.0; + scale[2] = ((1.0 - scale[0]) * (1.0 - data.bevelevation)) / 16.0; + int xMax = map.GetLength(0); + int yMax = map.GetLength(1); + double result; + if ((x == 0) || (y == 0) || (x == (xMax - 1)) || (y == (yMax - 1))) + { + result = map[x, y]; + } + else + { + result = 0.0; + for(int yPos = (y - 2); yPos < (y + 3); yPos++) + { + int yVal = (yPos <= 0) ? 0 : ((yPos < yMax) ? yPos : yMax - 1); + for(int xPos = (x - 2); xPos < (x + 3); xPos++) + { + int xVal = (xPos <= 0) ? 0 : ((xPos < xMax) ? xPos : xMax - 1); + int dist = Math.Max(Math.Abs(x - xVal), Math.Abs(y - yVal)); + result += map[xVal, yVal] * scale[dist]; + } + } + } + return result; + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs new file mode 100644 index 0000000..7ebd08e --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs @@ -0,0 +1,378 @@ +/* + * 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 System.Reflection; +using log4net; + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public abstract class TerrainModifier : ITerrainModifier + { + protected ITerrainModule m_module; + protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected TerrainModifier(ITerrainModule module) + { + m_module = module; + } + + public abstract string ModifyTerrain(ITerrainChannel map, string[] args); + + public abstract string GetUsage(); + + public abstract double operate(double[,] map, TerrainModifierData data, int x, int y); + + protected String parseParameters(string[] args, out TerrainModifierData data) + { + string val; + string arg; + string result; + data = new TerrainModifierData(); + data.shape = String.Empty; + data.bevel = String.Empty; + data.dx = 0; + data.dy = 0; + if (args.Length < 4) + { + result = "Usage: " + GetUsage(); + } + else + { + result = this.parseFloat(args[3], out data.elevation); + } + if (result == String.Empty) + { + int index = 3; + while(++index < args.Length && result == String.Empty) + { + arg = args[index]; + // check for shape + if (arg.StartsWith("-rec=") || arg.StartsWith("-ell=")) + { + if (data.shape != String.Empty) + { + result = "Only 1 '-rec' or '-ell' parameter is permitted."; + } + else + { + data.shape = arg.StartsWith("-ell=") ? "ellipse" : "rectangle"; + val = arg.Substring(arg.IndexOf("=") + 1); + string[] coords = val.Split(new char[] {','}); + if ((coords.Length < 3) || (coords.Length > 4)) + { + result = String.Format("Bad format for shape parameter {0}", arg); + } + else + { + result = this.parseInt(coords[0], out data.x0); + if (result == String.Empty) + { + result = this.parseInt(coords[1], out data.y0); + } + if (result == String.Empty) + { + result = this.parseInt(coords[2], out data.dx); + } + if (result == String.Empty) + { + if (coords.Length == 4) + { + result = this.parseInt(coords[3], out data.dy); + } + else + { + data.dy = data.dx; + } + } + if (result == String.Empty) + { + if ((data.dx <= 0) || (data.dy <= 0)) + { + result = "Shape sizes must be positive integers"; + } + } + else + { + result = String.Format("Bad value in shape parameters {0}", arg); + } + } + } + } + else if (arg.StartsWith("-taper=")) + { + if (data.bevel != String.Empty) + { + result = "Only 1 '-taper' parameter is permitted."; + } + else + { + data.bevel = "taper"; + val = arg.Substring(arg.IndexOf("=") + 1); + result = this.parseFloat(val, out data.bevelevation); + if (result != String.Empty) + { + result = String.Format("Bad format for taper parameter {0}", arg); + } + } + } + else + { + result = String.Format("Unrecognized parameter {0}", arg); + } + } + } + return result; + } + + protected string parseFloat(String s, out float f) + { + string result; + double d; + if (Double.TryParse(s, out d)) + { + try + { + f = (float)d; + result = String.Empty; + } + catch(InvalidCastException) + { + result = String.Format("{0} is invalid", s); + f = -1.0f; + } + } + else + { + f = -1.0f; + result = String.Format("{0} is invalid", s); + } + return result; + } + + protected string parseInt(String s, out int i) + { + string result; + if (Int32.TryParse(s, out i)) + { + result = String.Empty; + } + else + { + result = String.Format("{0} is invalid", s); + } + return result; + } + + protected void applyModification(ITerrainChannel map, TerrainModifierData data) + { + bool[,] mask; + int xMax; + int yMax; + int xMid; + int yMid; + if (data.shape == "ellipse") + { + mask = this.ellipticalMask(data.dx, data.dy); + xMax = mask.GetLength(0); + yMax = mask.GetLength(1); + xMid = xMax / 2 + xMax % 2; + yMid = yMax / 2 + yMax % 2; + } + else + { + mask = this.rectangularMask(data.dx, data.dy); + xMax = mask.GetLength(0); + yMax = mask.GetLength(1); + xMid = 0; + yMid = 0; + } +// m_log.DebugFormat("Apply {0} mask {1}x{2} @ {3},{4}", data.shape, xMax, yMax, xMid, yMid); + double[,] buffer = map.GetDoubles(); + int yDim = yMax; + while(--yDim >= 0) + { + int yPos = data.y0 + yDim - yMid; + if ((yPos >= 0) && (yPos < map.Height)) + { + int xDim = xMax; + while(--xDim >= 0) + { + int xPos = data.x0 + xDim - xMid; + if ((xPos >= 0) && (xPos < map.Width) && (mask[xDim, yDim])) + { + double endElevation = this.operate(buffer, data, xPos, yPos); + map[xPos, yPos] = endElevation; + } + } + } + } + } + + protected double computeBevel(TerrainModifierData data, int x, int y) + { + int deltaX; + int deltaY; + int xMax; + int yMax; + double factor; + if (data.bevel == "taper") + { + if (data.shape == "ellipse") + { + deltaX = x - data.x0; + deltaY = y - data.y0; + xMax = data.dx; + yMax = data.dy; + factor = (double)((deltaX * deltaX) + (deltaY * deltaY)); + factor /= ((xMax * xMax) + (yMax * yMax)); + } + else + { + // pyramid + xMax = data.dx / 2 + data.dx % 2; + yMax = data.dy / 2 + data.dy % 2; + deltaX = Math.Abs(data.x0 + xMax - x); + deltaY = Math.Abs(data.y0 + yMax - y); + factor = Math.Max(((double)(deltaY) / yMax), ((double)(deltaX) / xMax)); + } + } + else + { + factor = 0.0; + } + return factor; + } + + private bool[,] rectangularMask(int xSize, int ySize) + { + bool[,] mask = new bool[xSize, ySize]; + int yPos = ySize; + while(--yPos >= 0) + { + int xPos = xSize; + while(--xPos >= 0) + { + mask[xPos, yPos] = true; + } + } + return mask; + } + + /* + * Fast ellipse-based derivative of Bresenham algorithm. + * https://web.archive.org/web/20120225095359/http://homepage.smc.edu/kennedy_john/belipse.pdf + */ + private bool[,] ellipticalMask(int xRadius, int yRadius) + { + long twoASquared = 2L * xRadius * xRadius; + long twoBSquared = 2L * yRadius * yRadius; + + bool[,] mask = new bool[2 * xRadius + 1, 2 * yRadius + 1]; + + long ellipseError = 0L; + long stoppingX = twoBSquared * xRadius; + long stoppingY = 0L; + long xChange = yRadius * yRadius * (1L - 2L * xRadius); + long yChange = xRadius * xRadius; + + int xPos = xRadius; + int yPos = 0; + + // first set of points + while(stoppingX >= stoppingY) + { + int yUpper = yRadius + yPos; + int yLower = yRadius - yPos; + // fill in the mask + int xNow = xPos; + while(xNow >= 0) + { + mask[xRadius + xNow, yUpper] = true; + mask[xRadius - xNow, yUpper] = true; + mask[xRadius + xNow, yLower] = true; + mask[xRadius - xNow, yLower] = true; + --xNow; + } + yPos++; + stoppingY += twoASquared; + ellipseError += yChange; + yChange += twoASquared; + if ((2L * ellipseError + xChange) > 0L) + { + xPos--; + stoppingX -= twoBSquared; + ellipseError += xChange; + xChange += twoBSquared; + } + } + + // second set of points + xPos = 0; + yPos = yRadius; + xChange = yRadius * yRadius; + yChange = xRadius * xRadius * (1L - 2L * yRadius); + + ellipseError = 0L; + stoppingX = 0L; + stoppingY = twoASquared * yRadius; + + while(stoppingX <= stoppingY) + { + int xUpper = xRadius + xPos; + int xLower = xRadius - xPos; + // fill in the mask + int yNow = yPos; + while(yNow >= 0) + { + mask[xUpper, yRadius + yNow] = true; + mask[xUpper, yRadius - yNow] = true; + mask[xLower, yRadius + yNow] = true; + mask[xLower, yRadius - yNow] = true; + --yNow; + } + xPos++; + stoppingX += twoBSquared; + ellipseError += xChange; + xChange += twoBSquared; + if ((2L * ellipseError + yChange) > 0L) + { + yPos--; + stoppingY -= twoASquared; + ellipseError += yChange; + yChange += twoASquared; + } + } + return mask; + } + + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs new file mode 100644 index 0000000..4e0f8d7 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs @@ -0,0 +1,17 @@ +using System; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public struct TerrainModifierData + { + public float elevation; + public string shape; + public int x0; + public int y0; + public int dx; + public int dy; + public string bevel; + public float bevelevation; + } +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 3bb8040..02f21b9 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -24,7 +24,6 @@ * (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 System.Collections.Generic; using System.IO; @@ -43,6 +42,7 @@ using OpenSim.Framework.Console; using OpenSim.Region.CoreModules.Framework.InterfaceCommander; using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; using OpenSim.Region.CoreModules.World.Terrain.Features; +using OpenSim.Region.CoreModules.World.Terrain.Modifiers; using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; using OpenSim.Region.Framework.Interfaces; @@ -90,26 +90,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain #pragma warning restore 414 private readonly Commander m_commander = new Commander("terrain"); - private readonly Dictionary m_floodeffects = new Dictionary(); - private readonly Dictionary m_loaders = new Dictionary(); - private readonly Dictionary m_painteffects = new Dictionary(); - private Dictionary m_plugineffects; - private Dictionary m_featureEffects = new Dictionary(); - + private Dictionary m_modifyOperations = + new Dictionary(); private ITerrainChannel m_channel; private ITerrainChannel m_revert; private Scene m_scene; private volatile bool m_tainted; private readonly Stack m_undo = new Stack(5); - private String m_InitialTerrain = "pinhead-island"; // If true, send terrain patch updates to clients based on their view distance @@ -136,14 +131,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain { return (updateCount > 0); } + public void SetByXY(int x, int y, bool state) { this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state); } + public bool GetByPatch(int patchX, int patchY) { return updated[patchX, patchY]; } + public void SetByPatch(int patchX, int patchY, bool state) { bool prevState = updated[patchX, patchY]; @@ -153,11 +151,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain updateCount--; updated[patchX, patchY] = state; } + public void SetAll(bool state) { updateCount = 0; - for (int xx = 0; xx < updated.GetLength(0); xx++) - for (int yy = 0; yy < updated.GetLength(1); yy++) + for(int xx = 0; xx < updated.GetLength(0); xx++) + for(int yy = 0; yy < updated.GetLength(1); yy++) updated[xx, yy] = state; if (state) updateCount = updated.GetLength(0) * updated.GetLength(1); @@ -174,9 +173,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) ); } - for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) + for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) { - for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) + for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) { // Only set tainted. The patch bit may be set if the patch was to be sent later. if (terrData.IsTaintedAt(xx, yy, false)) @@ -201,8 +200,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain #region ICommandableModule Members - public ICommander CommandInterface - { + public ICommander CommandInterface { get { return m_commander; } } @@ -230,7 +228,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_scene = scene; // Install terrain module in the simulator - lock (m_scene) + lock(m_scene) { if (m_scene.Heightmap == null) { @@ -262,7 +260,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain string supportedFilesSeparatorForTileSave = ""; m_supportFileExtensionsForTileSave = ""; - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; supportedFilesSeparator = ", "; @@ -285,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain public void RemoveRegion(Scene scene) { - lock (m_scene) + lock(m_scene) { // remove the commands m_scene.UnregisterModuleCommander(m_commander.Name); @@ -304,13 +302,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain { } - public Type ReplaceableInterface - { + public Type ReplaceableInterface { get { return null; } } - public string Name - { + public string Name { get { return "TerrainModule"; } } @@ -329,11 +325,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// Filename to terrain file. Type is determined by extension. public void LoadFromFile(string filename) { - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { if (filename.EndsWith(loader.Key)) { - lock (m_scene) + lock(m_scene) { try { @@ -349,20 +345,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_channel = channel; UpdateRevertMap(); } - catch (NotImplementedException) + catch(NotImplementedException) { m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + " parser does not support file loading. (May be save only)"); throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); } - catch (FileNotFoundException) + catch(FileNotFoundException) { m_log.Error( "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); throw new TerrainException( String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); } - catch (ArgumentException e) + catch(ArgumentException e) { m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); throw new TerrainException( @@ -386,7 +382,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain { try { - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { if (filename.EndsWith(loader.Key)) { @@ -396,7 +392,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain } } } - catch (IOException ioe) + catch(IOException ioe) { m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message)); } @@ -429,11 +425,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain public void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream) { - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { if (filename.EndsWith(loader.Key)) { - lock (m_scene) + lock(m_scene) { try { @@ -441,7 +437,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); UpdateRevertMap(); } - catch (NotImplementedException) + catch(NotImplementedException) { m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + " parser does not support file loading. (May be save only)"); @@ -501,7 +497,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain { try { - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { if (filename.EndsWith(loader.Key)) { @@ -510,7 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain } } } - catch (NotImplementedException) + catch(NotImplementedException) { m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); @@ -519,12 +515,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. // ITerrainModule.TaintTerrain() - public void TaintTerrain () + public void TaintTerrain() { - lock (m_perClientPatchUpdates) + lock(m_perClientPatchUpdates) { // Set the flags for all clients so the tainted patches will be sent out - foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) + foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) { pups.SetAll(m_scene.Heightmap.GetTerrainData()); } @@ -539,7 +535,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); if (presence != null) { - lock (m_perClientPatchUpdates) + lock(m_perClientPatchUpdates) { PatchUpdates pups; if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) @@ -572,7 +568,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain return; string[] files = Directory.GetFiles(plugineffectsPath); - foreach (string file in files) + foreach(string file in files) { m_log.Info("Loading effects in " + file); try @@ -580,7 +576,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain Assembly library = Assembly.LoadFrom(file); LoadPlugins(library); } - catch (BadImageFormatException) + catch(BadImageFormatException) { } } @@ -588,7 +584,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void LoadPlugins(Assembly library) { - foreach (Type pluginType in library.GetTypes()) + foreach(Type pluginType in library.GetTypes()) { try { @@ -610,7 +606,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_log.Info("L ... " + typeName); } } - catch (AmbiguousMatchException) + catch(AmbiguousMatchException) { } } @@ -618,7 +614,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain public void InstallPlugin(string pluginName, ITerrainEffect effect) { - lock (m_plugineffects) + lock(m_plugineffects) { if (!m_plugineffects.ContainsKey(pluginName)) { @@ -664,6 +660,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain // Terrain Feature effects m_featureEffects["rectangle"] = new RectangleFeature(this); + // Terrain Modifier operations + m_modifyOperations["min"] = new MinModifier(this); + m_modifyOperations["max"] = new MaxModifier(this); + m_modifyOperations["raise"] = new RaiseModifier(this); + m_modifyOperations["lower"] = new LowerModifier(this); + m_modifyOperations["fill"] = new FillModifier(this); + m_modifyOperations["smooth"] = new SmoothModifier(this); + // Filesystem load/save loaders m_loaders[".r32"] = new RAW32(); m_loaders[".f32"] = m_loaders[".r32"]; @@ -707,22 +711,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// Where to begin our slice public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) { - int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; - int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; + int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX; + int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY; if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) { // this region is included in the tile request - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { if (filename.EndsWith(loader.Key)) { - lock (m_scene) + lock(m_scene) { ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, fileWidth, fileHeight, - (int) m_scene.RegionInfo.RegionSizeX, - (int) m_scene.RegionInfo.RegionSizeY); + (int)m_scene.RegionInfo.RegionSizeX, + (int)m_scene.RegionInfo.RegionSizeY); m_scene.Heightmap = channel; m_channel = channel; UpdateRevertMap(); @@ -761,11 +765,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain } // this region is included in the tile request - foreach (KeyValuePair loader in m_loaders) + foreach(KeyValuePair loader in m_loaders) { if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) { - lock (m_scene) + lock(m_scene) { loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, fileWidth, fileHeight, @@ -799,9 +803,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain TerrainData terrData = m_channel.GetTerrainData(); bool shouldTaint = false; - for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) + for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) { - for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) + for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) { if (terrData.IsTaintedAt(x, y)) { @@ -856,7 +860,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain string[] tmpArgs = new string[args.Length - 2]; int i; - for (i = 2; i < args.Length; i++) + for(i = 2; i < args.Length; i++) tmpArgs[i - 2] = args[i]; m_commander.ProcessConsoleCommand(args[1], tmpArgs); @@ -890,7 +894,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; } - lock (m_perClientPatchUpdates) + lock(m_perClientPatchUpdates) m_perClientPatchUpdates.Remove(client); } @@ -904,12 +908,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain TerrainData terrData = m_channel.GetTerrainData(); bool wasLimited = false; - for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) + for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) { - for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) + for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) { if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) - { + { // If we should respect the estate settings then // fixup and height deltas that don't respect them. // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. @@ -933,9 +937,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain // loop through the height map for this patch and compare it against // the revert map - for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) + for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) { - for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) + for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) { float requestedHeight = terrData[x, y]; float bakedHeight = (float)m_revert[x, y]; @@ -959,7 +963,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void client_OnLandUndo(IClientAPI client) { - lock (m_undo) + lock(m_undo) { if (m_undo.Count > 0) { @@ -981,19 +985,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain if (m_sendTerrainUpdatesByViewDistance) { // Add that this patch needs to be sent to the accounting for each client. - lock (m_perClientPatchUpdates) + lock(m_perClientPatchUpdates) { m_scene.ForEachScenePresence(presence => + { + PatchUpdates thisClientUpdates; + if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) { - PatchUpdates thisClientUpdates; - if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) - { - // There is a ScenePresence without a send patch map. Create one. - thisClientUpdates = new PatchUpdates(terrData, presence); - m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); - } - thisClientUpdates.SetByXY(x, y, true); + // There is a ScenePresence without a send patch map. Create one. + thisClientUpdates = new PatchUpdates(terrData, presence); + m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); } + thisClientUpdates.SetByXY(x, y, true); + } ); } } @@ -1005,11 +1009,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain float[] heightMap = new float[10]; m_scene.ForEachClient( delegate(IClientAPI controller) - { - controller.SendLayerData(x / Constants.TerrainPatchSize, + { + controller.SendLayerData(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, heightMap); - } + } ); } } @@ -1019,12 +1023,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain public int PatchX; public int PatchY; public float Dist; + public PatchesToSend(int pX, int pY, float pDist) { PatchX = pX; PatchY = pY; Dist = pDist; } + public int CompareTo(PatchesToSend other) { return Dist.CompareTo(other.Dist); @@ -1036,9 +1042,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain // Loop through all the per-client info and send any patches necessary. private void CheckSendingPatchesToClients() { - lock (m_perClientPatchUpdates) + lock(m_perClientPatchUpdates) { - foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) + foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) { if (pups.HasUpdates()) { @@ -1062,7 +1068,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain int[] yPieces = new int[toSend.Count]; float[] patchPieces = new float[toSend.Count * 2]; int pieceIndex = 0; - foreach (PatchesToSend pts in toSend) + foreach(PatchesToSend pts in toSend) { patchPieces[pieceIndex++] = pts.PatchX; patchPieces[pieceIndex++] = pts.PatchY; @@ -1083,25 +1089,25 @@ namespace OpenSim.Region.CoreModules.World.Terrain return ret; // Compute the area of patches within our draw distance - int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; + int startX = (((int)(presence.AbsolutePosition.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; startX = Math.Max(startX, 0); - startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); - int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; + startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); + int startY = (((int)(presence.AbsolutePosition.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; startY = Math.Max(startY, 0); - startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); - int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; + startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); + int endX = (((int)(presence.AbsolutePosition.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; endX = Math.Max(endX, 0); - endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); - int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; + endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); + int endY = (((int)(presence.AbsolutePosition.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; endY = Math.Max(endY, 0); - endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); + endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>", // LogHeader, m_scene.RegionInfo.RegionName, // presence.DrawDistance, presence.AbsolutePosition, // startX, startY, endX, endY); - for (int x = startX; x < endX; x++) + for(int x = startX; x < endX; x++) { - for (int y = startY; y < endY; y++) + for(int y = startY; y < endY; y++) { //Need to make sure we don't send the same ones over and over Vector3 presencePos = presence.AbsolutePosition; @@ -1133,28 +1139,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain bool allowed = false; if (north == south && east == west) { - if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) + if (m_painteffects.ContainsKey((StandardTerrainEffects)action)) { - bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; + bool[,] allowMask = new bool[m_channel.Width, m_channel.Height]; allowMask.Initialize(); int n = size + 1; if (n > 2) n = 4; - int zx = (int) (west + 0.5); - int zy = (int) (north + 0.5); + int zx = (int)(west + 0.5); + int zy = (int)(north + 0.5); int dx; - for (dx=-n; dx<=n; dx++) + for(dx=-n; dx<=n; dx++) { int dy; - for (dy=-n; dy<=n; dy++) + for(dy=-n; dy<=n; dy++) { int x = zx + dx; int y = zy + dy; - if (x>=0 && y>=0 && x= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height) { - if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) + if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) { allowMask[x, y] = true; allowed = true; @@ -1165,7 +1171,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain if (allowed) { StoreUndoState(); - m_painteffects[(StandardTerrainEffects) action].PaintEffect( + m_painteffects[(StandardTerrainEffects)action].PaintEffect( m_channel, allowMask, west, south, height, size, seconds); //revert changes outside estate limits @@ -1180,22 +1186,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain } else { - if (m_floodeffects.ContainsKey((StandardTerrainEffects) action)) + if (m_floodeffects.ContainsKey((StandardTerrainEffects)action)) { - bool[,] fillArea = new bool[m_channel.Width,m_channel.Height]; + bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; fillArea.Initialize(); int x; - for (x = 0; x < m_channel.Width; x++) + for(x = 0; x < m_channel.Width; x++) { int y; - for (y = 0; y < m_channel.Height; y++) + for(y = 0; y < m_channel.Height; y++) { if (x < east && x > west) { if (y < north && y > south) { - if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) + if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) { fillArea[x, y] = true; allowed = true; @@ -1208,7 +1214,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain if (allowed) { StoreUndoState(); - m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size); + m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size); //revert changes outside estate limits if (!god) @@ -1243,7 +1249,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void StoreUndoState() { - lock (m_undo) + lock(m_undo) { if (m_undo.Count > 0) { @@ -1264,21 +1270,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceLoadFile(Object[] args) { - LoadFromFile((string) args[0]); + LoadFromFile((string)args[0]); } private void InterfaceLoadTileFile(Object[] args) { - LoadFromFile((string) args[0], - (int) args[1], - (int) args[2], - (int) args[3], - (int) args[4]); + LoadFromFile((string)args[0], + (int)args[1], + (int)args[2], + (int)args[3], + (int)args[4]); } private void InterfaceSaveFile(Object[] args) { - SaveToFile((string) args[0]); + SaveToFile((string)args[0]); } private void InterfaceSaveTileFile(Object[] args) @@ -1298,8 +1304,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceRevertTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) + for(x = 0; x < m_channel.Width; x++) + for(y = 0; y < m_channel.Height; y++) m_channel[x, y] = m_revert[x, y]; } @@ -1310,9 +1316,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain if (direction.ToLower().StartsWith("y")) { - for (int x = 0; x < m_channel.Width; x++) + for(int x = 0; x < m_channel.Width; x++) { - for (int y = 0; y < m_channel.Height / 2; y++) + for(int y = 0; y < m_channel.Height / 2; y++) { double height = m_channel[x, y]; double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; @@ -1324,9 +1330,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain } else if (direction.ToLower().StartsWith("x")) { - for (int y = 0; y < m_channel.Height; y++) + for(int y = 0; y < m_channel.Height; y++) { - for (int x = 0; x < m_channel.Width / 2; x++) + for(int x = 0; x < m_channel.Width / 2; x++) { double height = m_channel[x, y]; double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; @@ -1365,9 +1371,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain int width = m_channel.Width; int height = m_channel.Height; - for (int x = 0; x < width; x++) + for(int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) + for(int y = 0; y < height; y++) { double currHeight = m_channel[x, y]; if (currHeight < currMin) @@ -1388,12 +1394,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain //m_log.InfoFormat("Scale = {0}", scale); // scale the heightmap accordingly - for (int x = 0; x < width; x++) + for(int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) + for(int y = 0; y < height; y++) { - double currHeight = m_channel[x, y] - currMin; - m_channel[x, y] = desiredMin + (currHeight * scale); + double currHeight = m_channel[x, y] - currMin; + m_channel[x, y] = desiredMin + (currHeight * scale); } } @@ -1404,42 +1410,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceElevateTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] += (double) args[0]; + for(x = 0; x < m_channel.Width; x++) + for(y = 0; y < m_channel.Height; y++) + m_channel[x, y] += (double)args[0]; } private void InterfaceMultiplyTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] *= (double) args[0]; + for(x = 0; x < m_channel.Width; x++) + for(y = 0; y < m_channel.Height; y++) + m_channel[x, y] *= (double)args[0]; } private void InterfaceLowerTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] -= (double) args[0]; + for(x = 0; x < m_channel.Width; x++) + for(y = 0; y < m_channel.Height; y++) + m_channel[x, y] -= (double)args[0]; } public void InterfaceFillTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] = (double) args[0]; + for(x = 0; x < m_channel.Width; x++) + for(y = 0; y < m_channel.Height; y++) + m_channel[x, y] = (double)args[0]; } private void InterfaceMinTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) + for(x = 0; x < m_channel.Width; x++) { - for (y = 0; y < m_channel.Height; y++) + for(y = 0; y < m_channel.Height; y++) { m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); } @@ -1449,9 +1455,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceMaxTerrain(Object[] args) { int x, y; - for (x = 0; x < m_channel.Width; x++) + for(x = 0; x < m_channel.Width; x++) { - for (y = 0; y < m_channel.Height; y++) + for(y = 0; y < m_channel.Height; y++) { m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); } @@ -1480,10 +1486,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain double sum = 0; int x; - for (x = 0; x < m_channel.Width; x++) + for(x = 0; x < m_channel.Width; x++) { int y; - for (y = 0; y < m_channel.Height; y++) + for(y = 0; y < m_channel.Height; y++) { sum += m_channel[x, y]; if (max < m_channel[x, y]) @@ -1501,7 +1507,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceEnableExperimentalBrushes(Object[] args) { - if ((bool) args[0]) + if ((bool)args[0]) { m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); @@ -1520,7 +1526,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain if (firstArg == "list") { MainConsole.Instance.Output("List of loaded plugins"); - foreach (KeyValuePair kvp in m_plugineffects) + foreach(KeyValuePair kvp in m_plugineffects) { MainConsole.Instance.Output(kvp.Key); } @@ -1668,6 +1674,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain // Add Feature command to Scene, since Command object requires fixed-length arglists m_scene.AddCommand("Terrain", this, "terrain feature", "terrain feature ", "Constructs a feature of the requested type.", FeatureCommand); + // Add Modify command to Scene, since Command object requires fixed-length arglists + m_scene.AddCommand("Terrain", this, "terrain modify", + "terrain modify [] []", + "Modifies the terrain as instructed." + + "\nEach operation can be limited to an area of effect:" + + "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" + + "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" + + "\nEach operation can have its effect tapered based on distance from centre:" + + "\n * elliptical operations taper as cones" + + "\n * rectangular operations taper as pyramids" + , + ModifyCommand); } @@ -1683,7 +1701,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain { result = String.Format("Terrain Feature \"{0}\" not found.", featureType); } - else if ((cmd.Length > 3) && (cmd[3] == "usage")) + else if ((cmd.Length > 3) && (cmd[3] == "usage")) { result = "Usage: " + feature.GetUsage(); } @@ -1692,7 +1710,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain result = feature.CreateFeature(m_channel, cmd); } - if(result == String.Empty) + if (result == String.Empty) { result = "Created Feature"; m_log.DebugFormat("Created terrain feature {0}", featureType); @@ -1704,7 +1722,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain } MainConsole.Instance.Output(result); } - #endregion + + public void ModifyCommand(string module, string[] cmd) + { + string result; + if (cmd.Length > 2) + { + string operationType = cmd[2]; + + ITerrainModifier operation; + if (!m_modifyOperations.TryGetValue(operationType, out operation)) + { + result = String.Format("Terrain Modify \"{0}\" not found.", operationType); + } + else if ((cmd.Length > 3) && (cmd[3] == "usage")) + { + result = "Usage: " + operation.GetUsage(); + } + else + { + result = operation.ModifyTerrain(m_channel, cmd); + } + + if (result == String.Empty) + { + result = "Modified terrain"; + m_log.DebugFormat("Performed terrain operation {0}", operationType); + } + } + else + { + result = "Usage: ..."; + } + MainConsole.Instance.Output(result); + } + +#endregion } } -- cgit v1.1 From a9dd3028b94b35fb9c504b05466522cd2f9be306 Mon Sep 17 00:00:00 2001 From: Dev Random Date: Thu, 7 May 2015 13:25:36 -0400 Subject: Add 'terrain modify noise' and code cleanup Signed-off-by: Michael Cerquoni --- .../World/Terrain/Features/RectangleFeature.cs | 149 --------------------- .../World/Terrain/Modifiers/NoiseModifier.cs | 110 +++++++++++++++ .../World/Terrain/Modifiers/SmoothModifier.cs | 4 +- .../CoreModules/World/Terrain/TerrainFeature.cs | 89 ------------ .../CoreModules/World/Terrain/TerrainModule.cs | 52 +------ 5 files changed, 113 insertions(+), 291 deletions(-) delete mode 100644 OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs delete mode 100644 OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs b/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs deleted file mode 100644 index 33c3fbe..0000000 --- a/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.CoreModules.World.Terrain.Features -{ - public class RectangleFeature : TerrainFeature - { - public RectangleFeature(ITerrainModule module) : base(module) - { - } - - public override string CreateFeature(ITerrainChannel map, string[] args) - { - string val; - string result; - if (args.Length < 7) - { - result = "Usage: " + GetUsage(); - } - else - { - result = String.Empty; - - float targetElevation; - val = base.parseFloat(args[3], out targetElevation); - if (val != String.Empty) - { - result = val; - } - - int xOrigin; - val = base.parseInt(args[4], out xOrigin); - if (val != String.Empty) - { - result = val; - } - else if (xOrigin < 0 || xOrigin >= map.Width) - { - result = "x-origin must be within the region"; - } - - int yOrigin; - val = base.parseInt(args[5], out yOrigin); - if (val != String.Empty) - { - result = val; - } - else if (yOrigin < 0 || yOrigin >= map.Height) - { - result = "y-origin must be within the region"; - } - - int xDelta; - val = base.parseInt(args[6], out xDelta); - if (val != String.Empty) - { - result = val; - } - else if (xDelta <= 0) - { - result = "x-size must be greater than zero"; - } - - int yDelta; - if (args.Length > 7) - { - val = base.parseInt(args[7], out yDelta); - if (val != String.Empty) - { - result = val; - } - else if (yDelta <= 0) - { - result = "y-size must be greater than zero"; - } - } - else - { - // no y-size.. make it square - yDelta = xDelta; - } - - // slightly more complex validation, if required. - if (result == String.Empty) - { - if (xOrigin + xDelta > map.Width) - { - result = "(x-origin + x-size) must be within the region size"; - } - else if (yOrigin + yDelta > map.Height) - { - result = "(y-origin + y-size) must be within the region size"; - } - } - - // if it's all good, then do the work - if (result == String.Empty) - { - int yPos = yOrigin + yDelta; - while(--yPos >= yOrigin) - { - int xPos = xOrigin + xDelta; - while(--xPos >= xOrigin) - { - map[xPos, yPos] = (double)targetElevation; - } - } - } - } - - return result; - } - - public override string GetUsage() - { - return "rectangle []"; - } - } - -} - diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs new file mode 100644 index 0000000..b31bab1 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs @@ -0,0 +1,110 @@ +/* + * 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.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers +{ + public class NoiseModifier : TerrainModifier + { + public NoiseModifier(ITerrainModule module) : base(module) + { + } + + public override string ModifyTerrain(ITerrainChannel map, string[] args) + { + string val; + string result; + if (args.Length < 3) + { + result = "Usage: " + GetUsage(); + } + else + { + TerrainModifierData data; + result = this.parseParameters(args, out data); + + // Context-specific validation + if (result == String.Empty) + { + if (data.bevel == "taper") + { + if (data.bevelevation < 0.0 || data.bevelevation > 1.0) + { + result = String.Format("Taper must be 0.0 to 1.0: {0}", data.bevelevation); + } + } + else + { + data.bevelevation = 1.0f; + } + + if (data.elevation < 0.0 || data.elevation > 1.0) + { + result = String.Format("Noise strength must be 0.0 to 1.0: {0}", data.elevation); + } + + if (data.shape == String.Empty) + { + data.shape = "rectangle"; + data.x0 = 0; + data.y0 = 0; + data.dx = map.Width; + data.dy = map.Height; + } + } + + // if it's all good, then do the work + if (result == String.Empty) + { + this.applyModification(map, data); + } + } + + return result; + } + + public override string GetUsage() + { + string val = "noise [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=]" + + "\nAdds noise to all points within the specified range."; + return val; + } + + public override double operate(double[,] map, TerrainModifierData data, int x, int y) + { + double factor = this.computeBevel(data, x, y); + double noise = TerrainUtil.PerlinNoise2D((double)x / map.GetLength(0), (double)y / map.GetLength(1), 8, 1.0); + return map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor) * (noise - .5); + } + + } + +} + diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs index 1731cd8..72b172c 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs @@ -56,7 +56,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers { if (data.bevelevation < 0.01 || data.bevelevation > 0.99) { - result = String.Format("Taper must be 0.01 to 0.99 {0}", data.bevelevation); + result = String.Format("Taper must be 0.01 to 0.99: {0}", data.bevelevation); } } else @@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers if (data.elevation < 0.0 || data.elevation > 1.0) { - result = String.Format("Scaling factor must be 0.0 to 1.0: {0}", data.elevation); + result = String.Format("Smoothing strength must be 0.0 to 1.0: {0}", data.elevation); } if (data.shape == String.Empty) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs deleted file mode 100644 index 701a729..0000000 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 System.Reflection; - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.CoreModules.World.Terrain -{ - public abstract class TerrainFeature : ITerrainFeature - { - protected ITerrainModule m_module; - - protected TerrainFeature(ITerrainModule module) - { - m_module = module; - } - - public abstract string CreateFeature(ITerrainChannel map, string[] args); - - public abstract string GetUsage(); - - protected string parseFloat(String s, out float f) - { - string result; - double d; - if (Double.TryParse(s, out d)) - { - try - { - f = (float)d; - result = String.Empty; - } - catch(InvalidCastException) - { - result = String.Format("{0} is invalid", s); - f = -1.0f; - } - } - else - { - f = -1.0f; - result = String.Format("{0} is invalid", s); - } - return result; - } - - protected string parseInt(String s, out int i) - { - string result; - if (Int32.TryParse(s, out i)) - { - result = String.Empty; - } - else - { - result = String.Format("{0} is invalid", s); - } - return result; - } - - } - -} - diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 02f21b9..05c5fca 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -41,7 +41,6 @@ using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Region.CoreModules.Framework.InterfaceCommander; using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; -using OpenSim.Region.CoreModules.World.Terrain.Features; using OpenSim.Region.CoreModules.World.Terrain.Modifiers; using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; @@ -75,14 +74,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain #endregion - /// - /// Terrain Features - /// - public enum TerrainFeatures: byte - { - Rectangle = 1, - } - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); #pragma warning disable 414 @@ -96,8 +87,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain private readonly Dictionary m_painteffects = new Dictionary(); private Dictionary m_plugineffects; - private Dictionary m_featureEffects = - new Dictionary(); private Dictionary m_modifyOperations = new Dictionary(); private ITerrainChannel m_channel; @@ -657,9 +646,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); - // Terrain Feature effects - m_featureEffects["rectangle"] = new RectangleFeature(this); - // Terrain Modifier operations m_modifyOperations["min"] = new MinModifier(this); m_modifyOperations["max"] = new MaxModifier(this); @@ -667,6 +653,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_modifyOperations["lower"] = new LowerModifier(this); m_modifyOperations["fill"] = new FillModifier(this); m_modifyOperations["smooth"] = new SmoothModifier(this); + m_modifyOperations["noise"] = new NoiseModifier(this); // Filesystem load/save loaders m_loaders[".r32"] = new RAW32(); @@ -1671,9 +1658,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain // Add this to our scene so scripts can call these functions m_scene.RegisterModuleCommander(m_commander); - // Add Feature command to Scene, since Command object requires fixed-length arglists - m_scene.AddCommand("Terrain", this, "terrain feature", - "terrain feature ", "Constructs a feature of the requested type.", FeatureCommand); // Add Modify command to Scene, since Command object requires fixed-length arglists m_scene.AddCommand("Terrain", this, "terrain modify", "terrain modify [] []", @@ -1689,40 +1673,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain } - public void FeatureCommand(string module, string[] cmd) - { - string result; - if (cmd.Length > 2) - { - string featureType = cmd[2]; - - ITerrainFeature feature; - if (!m_featureEffects.TryGetValue(featureType, out feature)) - { - result = String.Format("Terrain Feature \"{0}\" not found.", featureType); - } - else if ((cmd.Length > 3) && (cmd[3] == "usage")) - { - result = "Usage: " + feature.GetUsage(); - } - else - { - result = feature.CreateFeature(m_channel, cmd); - } - - if (result == String.Empty) - { - result = "Created Feature"; - m_log.DebugFormat("Created terrain feature {0}", featureType); - } - } - else - { - result = "Usage: ..."; - } - MainConsole.Instance.Output(result); - } - public void ModifyCommand(string module, string[] cmd) { string result; -- cgit v1.1 From dc4c9b1bb0c3b3ac628135450776a2854d5014e5 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni Date: Thu, 7 May 2015 14:09:29 -0400 Subject: Minor whitespace removal --- OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs index b31bab1..53a64df 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs @@ -107,4 +107,3 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers } } - -- cgit v1.1 From cc1fc400d86440c49c62888a9fc39dd162f3c8e4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 7 May 2015 12:37:49 -0700 Subject: pCampbot: added behavior that mimic initial inventory download. It's not exactly what the viewer does, but it's close enough, and the elapsed time can be measured. --- .../Behaviours/InventoryDownloadBehaviour.cs | 121 +++++++++++++++++++++ OpenSim/Tools/pCampBot/BotManager.cs | 3 + 2 files changed, 124 insertions(+) create mode 100644 OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs (limited to 'OpenSim') diff --git a/OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs new file mode 100644 index 0000000..521415c --- /dev/null +++ b/OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs @@ -0,0 +1,121 @@ +/* + * 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 OpenMetaverse; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Linq; +using pCampBot.Interfaces; + +namespace pCampBot +{ + /// + /// Do nothing + /// + public class InventoryDownloadBehaviour : AbstractBehaviour + { + private bool m_initialized; + private int m_Requests = 2; + private Stopwatch m_StopWatch = new Stopwatch(); + private List m_processed = new List(); + + public InventoryDownloadBehaviour() + { + AbbreviatedName = "inv"; + Name = "Inventory"; + } + + public override void Action() + { + if (!m_initialized) + { + m_initialized = true; + Bot.Client.Settings.HTTP_INVENTORY = true; + Bot.Client.Settings.FETCH_MISSING_INVENTORY = true; + Bot.Client.Inventory.FolderUpdated += Inventory_FolderUpdated; + Console.WriteLine("Lib owner is " + Bot.Client.Inventory.Store.LibraryRootNode.Data.OwnerID); + m_StopWatch.Start(); + Bot.Client.Inventory.RequestFolderContents(Bot.Client.Inventory.Store.RootFolder.UUID, Bot.Client.Self.AgentID, true, true, InventorySortOrder.ByDate); + Bot.Client.Inventory.RequestFolderContents(Bot.Client.Inventory.Store.LibraryRootNode.Data.UUID, Bot.Client.Inventory.Store.LibraryRootNode.Data.OwnerID, true, true, InventorySortOrder.ByDate); + } + + Thread.Sleep(1000); + Console.WriteLine("Total items: " + Bot.Client.Inventory.Store.Items.Count + "; Total requests: " + m_Requests + "; Time: " + m_StopWatch.Elapsed); + + } + + void Inventory_FolderUpdated(object sender, FolderUpdatedEventArgs e) + { + if (e.Success) + { + //Console.WriteLine("Folder " + e.FolderID + " updated"); + bool fetch = false; + lock (m_processed) + { + if (!m_processed.Contains(e.FolderID)) + { + m_processed.Add(e.FolderID); + fetch = true; + } + } + + if (fetch) + { + List m_foldersToFetch = new List(); + foreach (InventoryBase item in Bot.Client.Inventory.Store.GetContents(e.FolderID)) + { + if (item is InventoryFolder) + { + InventoryFolder f = new InventoryFolder(item.UUID); + f.OwnerID = item.OwnerID; + m_foldersToFetch.Add(f); + } + } + if (m_foldersToFetch.Count > 0) + { + m_Requests += 1; + Bot.Client.Inventory.RequestFolderContentsCap(m_foldersToFetch, Bot.Client.Network.CurrentSim.Caps.CapabilityURI("FetchInventoryDescendents2"), true, true, InventorySortOrder.ByDate); + } + } + + if (Bot.Client.Inventory.Store.Items.Count >= 15739) + { + m_StopWatch.Stop(); + Console.WriteLine("Stop! Total items: " + Bot.Client.Inventory.Store.Items.Count + "; Total requests: " + m_Requests + "; Time: " + m_StopWatch.Elapsed); + } + } + + } + + public override void Interrupt() + { + m_interruptEvent.Set(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs index 46094d6..0af9592 100644 --- a/OpenSim/Tools/pCampBot/BotManager.cs +++ b/OpenSim/Tools/pCampBot/BotManager.cs @@ -343,6 +343,9 @@ namespace pCampBot if (abName == "ph2") newBehaviour = new PhysicsBehaviour2(); + if (abName == "inv") + newBehaviour = new InventoryDownloadBehaviour(); + if (newBehaviour != null) { behaviours.Add(newBehaviour); -- cgit v1.1 From c74cef0f4261191962959e42c7e349adafd42a04 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 7 May 2015 19:24:08 -0700 Subject: Major change in the way inventory is downloaded: added a method throughout IIventoryService that fetches sets of folders at once. Also added folder id in the InventoryCollection data structure, so that we don't need to go to inventory server again just for that. This reduces the chatter between sims and inventory server by... a lot. On my tests, this reduces initial inventory download down to 30% of what it currently is. --- .../FetchInvDescHandler.cs | 449 +++++++++++++++++---- OpenSim/Framework/InventoryCollection.cs | 4 +- .../Linden/Caps/WebFetchInvDescModule.cs | 6 +- .../Framework/Library/LocalInventoryService.cs | 14 +- .../Inventory/HGInventoryBroker.cs | 19 + .../Inventory/InventoryCache.cs | 2 +- .../Inventory/LocalInventoryServiceConnector.cs | 13 + .../Inventory/RemoteXInventoryServiceConnector.cs | 5 + .../Handlers/Inventory/XInventoryInConnector.cs | 74 +++- .../Inventory/XInventoryServicesConnector.cs | 81 +++- .../SimianGrid/SimianInventoryServiceConnector.cs | 16 +- .../HypergridService/HGInventoryService.cs | 9 +- OpenSim/Services/Interfaces/IInventoryService.cs | 8 + .../Services/InventoryService/XInventoryService.cs | 21 +- 14 files changed, 626 insertions(+), 95 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index 451575f..a2f6740 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -57,104 +57,113 @@ namespace OpenSim.Capabilities.Handlers m_LibraryService = libService; } + public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { -// lock (m_fetchLock) -// { -// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request); - // nasty temporary hack here, the linden client falsely - // identifies the uuid 00000000-0000-0000-0000-000000000000 - // as a string which breaks us - // - // correctly mark it as a uuid - // - request = request.Replace("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000"); + // nasty temporary hack here, the linden client falsely + // identifies the uuid 00000000-0000-0000-0000-000000000000 + // as a string which breaks us + // + // correctly mark it as a uuid + // + request = request.Replace("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000"); - // another hack 1 results in a - // System.ArgumentException: Object type System.Int32 cannot - // be converted to target type: System.Boolean - // - request = request.Replace("fetch_folders0", "fetch_folders0"); - request = request.Replace("fetch_folders1", "fetch_folders1"); + // another hack 1 results in a + // System.ArgumentException: Object type System.Int32 cannot + // be converted to target type: System.Boolean + // + request = request.Replace("fetch_folders0", "fetch_folders0"); + request = request.Replace("fetch_folders1", "fetch_folders1"); - Hashtable hash = new Hashtable(); + Hashtable hash = new Hashtable(); + try + { + hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); + } + catch (LLSD.LLSDParseException e) + { + m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); + m_log.Error("Request: " + request); + } + + ArrayList foldersrequested = (ArrayList)hash["folders"]; + + string response = ""; + string bad_folders_response = ""; + + List folders = new List(); + for (int i = 0; i < foldersrequested.Count; i++) + { + Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + + LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + try { - hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); + LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); } - catch (LLSD.LLSDParseException e) + catch (Exception e) { - m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); - m_log.Error("Request: " + request); + m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); + continue; } - - ArrayList foldersrequested = (ArrayList)hash["folders"]; - - string response = ""; - string bad_folders_response = ""; - for (int i = 0; i < foldersrequested.Count; i++) - { - string inventoryitemstr = ""; - Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + folders.Add(llsdRequest); + } - LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + if (folders.Count > 0) + { + List invcollSet = Fetch(folders); + //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); + if (invcollSet == null) + { + m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol."); + return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse); + } - try - { - LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); - } - catch (Exception e) - { - m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); - } - LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); + string inventoryitemstr = string.Empty; + foreach (InventoryCollectionWithDescendents icoll in invcollSet) + { + LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents); - if (null == reply) - { - bad_folders_response += "" + llsdRequest.folder_id.ToString() + ""; - } - else - { - inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); - inventoryitemstr = inventoryitemstr.Replace("folders", ""); - inventoryitemstr = inventoryitemstr.Replace("", ""); - } + inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); + inventoryitemstr = inventoryitemstr.Replace("folders", ""); + inventoryitemstr = inventoryitemstr.Replace("", ""); response += inventoryitemstr; } + } - if (response.Length == 0) + if (response.Length == 0) + { + /* Viewers expect a bad_folders array when not available */ + if (bad_folders_response.Length != 0) { - /* Viewers expect a bad_folders array when not available */ - if (bad_folders_response.Length != 0) - { - response = "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders"; - } + response = "bad_folders" + bad_folders_response + ""; } else { - if (bad_folders_response.Length != 0) - { - response = "folders" + response + "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders" + response + ""; - } + response = "folders"; } + } + else + { + if (bad_folders_response.Length != 0) + { + response = "folders" + response + "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders" + response + ""; + } + } -// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); - //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); +// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); +// m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); - return response; + return response; -// } } /// @@ -203,18 +212,130 @@ namespace OpenSim.Capabilities.Handlers contents.descendents = descendents; contents.version = version; -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", -// invFetch.folder_id, -// invFetch.fetch_items, -// invFetch.fetch_folders, -// contents.items.Array.Count, -// contents.categories.Array.Count, -// invFetch.owner_id); + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", + // invFetch.folder_id, + // invFetch.fetch_items, + // invFetch.fetch_folders, + // contents.items.Array.Count, + // contents.categories.Array.Count, + // invFetch.owner_id); return reply; } + private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) + { + LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); + LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); + contents.agent_id = inv.OwnerID; + contents.owner_id = inv.OwnerID; + contents.folder_id = inv.FolderID; + + reply.folders.Array.Add(contents); + + if (inv.Folders != null) + { + foreach (InventoryFolderBase invFolder in inv.Folders) + { + contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); + } + + descendents += inv.Folders.Count; + } + + if (inv.Items != null) + { + foreach (InventoryItemBase invItem in inv.Items) + { + contents.items.Array.Add(ConvertInventoryItem(invItem)); + } + } + + contents.descendents = descendents; + contents.version = inv.Version; + + return reply; + } + /// + /// Old style. Soon to be deprecated. + /// + /// + /// + /// + /// + [Obsolete] + private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count); + + string response = ""; + string bad_folders_response = ""; + + for (int i = 0; i < foldersrequested.Count; i++) + { + string inventoryitemstr = ""; + Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + + LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + + try + { + LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); + } + catch (Exception e) + { + m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); + } + + LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); + + if (null == reply) + { + bad_folders_response += "" + llsdRequest.folder_id.ToString() + ""; + } + else + { + inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); + inventoryitemstr = inventoryitemstr.Replace("folders", ""); + inventoryitemstr = inventoryitemstr.Replace("", ""); + } + + response += inventoryitemstr; + } + + if (response.Length == 0) + { + /* Viewers expect a bad_folders array when not available */ + if (bad_folders_response.Length != 0) + { + response = "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders"; + } + } + else + { + if (bad_folders_response.Length != 0) + { + response = "folders" + response + "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders" + response + ""; + } + } + + // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); + //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); + + return response; + + // } + } + /// /// Handle the caps inventory descendents fetch. /// @@ -226,6 +347,7 @@ namespace OpenSim.Capabilities.Handlers /// /// /// An empty InventoryCollection if the inventory look up failed + [Obsolete] private InventoryCollection Fetch( UUID agentID, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents) @@ -264,7 +386,6 @@ namespace OpenSim.Capabilities.Handlers m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID); return contents; } - contents = fetchedContents; InventoryFolderBase containingFolder = new InventoryFolderBase(); containingFolder.ID = folderID; @@ -273,9 +394,9 @@ namespace OpenSim.Capabilities.Handlers if (containingFolder != null) { -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", -// containingFolder.Name, containingFolder.ID, agentID); + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", + // containingFolder.Name, containingFolder.ID, agentID); version = containingFolder.Version; @@ -410,6 +531,160 @@ namespace OpenSim.Capabilities.Handlers return contents; } + + private void AddLibraryFolders(List fetchFolders, List result) + { + InventoryFolderImpl fold; + if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) + { + List libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); + fetchFolders.RemoveAll(f => libfolders.Contains(f)); + + foreach (LLSDFetchInventoryDescendents f in libfolders) + { + if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) + { + InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); + ret.Collection = new InventoryCollection(); + ret.Collection.Folders = new List(); + ret.Collection.Items = fold.RequestListOfItems(); + ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; + ret.Collection.FolderID = f.folder_id; + ret.Collection.Version = fold.Version; + + ret.Descendents = ret.Collection.Items.Count; + + result.Add(ret); + } + } + } + } + + private List Fetch(List fetchFolders) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); + + // FIXME MAYBE: We're not handling sortOrder! + + List result = new List(); + + AddLibraryFolders(fetchFolders, result); + + if (fetchFolders.Count > 0) + { + UUID[] fids = new UUID[fetchFolders.Count]; + int i = 0; + foreach (LLSDFetchInventoryDescendents f in fetchFolders) + fids[i++] = f.folder_id; + + InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); + + if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) + { + //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); + return null; + } + + i = 0; + // Do some post-processing. May need to fetch more from inv server for links + foreach (InventoryCollection contents in fetchedContents) + { + InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); + coll.Collection = contents; + + // Find the original request + LLSDFetchInventoryDescendents freq = fetchFolders[i++]; + + // The inventory server isn't sending FolderID in the collection... + // Must fetch it individually + if (contents.FolderID == UUID.Zero) + { + InventoryFolderBase containingFolder = new InventoryFolderBase(); + containingFolder.ID = freq.folder_id; + containingFolder.Owner = freq.owner_id; + containingFolder = m_InventoryService.GetFolder(containingFolder); + + if (containingFolder != null) + { + contents.FolderID = containingFolder.ID; + contents.OwnerID = containingFolder.Owner; + contents.Version = containingFolder.Version; + } + else + { + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); + continue; + } + } + + if (freq.fetch_items && contents.Items != null) + { + List itemsToReturn = contents.Items; + List originalItems = new List(itemsToReturn); + + // descendents must only include the links, not the linked items we add + coll.Descendents = originalItems.Count; + + // Add target items for links in this folder before the links themselves. + foreach (InventoryItemBase item in originalItems) + { + if (item.AssetType == (int)AssetType.Link) + { + InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); + + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) + { + itemsToReturn.Insert(0, linkedItem); + } + } + } + + // Now scan for folder links and insert the items they target and those links at the head of the return data + foreach (InventoryItemBase item in originalItems) + { + if (item.AssetType == (int)AssetType.LinkFolder) + { + InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(coll.Collection.OwnerID, item.AssetID); + List links = linkedFolderContents.Items; + + itemsToReturn.InsertRange(0, links); + + foreach (InventoryItemBase link in linkedFolderContents.Items) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (link != null) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", + // link.Name, (AssetType)link.AssetType, item.AssetID, contents.FolderID); + + InventoryItemBase linkedItem + = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); + + if (linkedItem != null) + itemsToReturn.Insert(0, linkedItem); + } + } + } + } + } + + result.Add(coll); + } + } + + return result; + } + + /// /// Convert an internal inventory folder object into an LLSD object. /// @@ -462,4 +737,10 @@ namespace OpenSim.Capabilities.Handlers return llsdItem; } } + + struct InventoryCollectionWithDescendents + { + public InventoryCollection Collection; + public int Descendents; + } } \ No newline at end of file diff --git a/OpenSim/Framework/InventoryCollection.cs b/OpenSim/Framework/InventoryCollection.cs index 7049902..59655eb 100644 --- a/OpenSim/Framework/InventoryCollection.cs +++ b/OpenSim/Framework/InventoryCollection.cs @@ -37,6 +37,8 @@ namespace OpenSim.Framework { public List Folders; public List Items; - public UUID UserID; + public UUID OwnerID; + public UUID FolderID; + public int Version; } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index e402b0b..30d1921 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -201,7 +201,7 @@ namespace OpenSim.Region.ClientStack.Linden Scene.EventManager.OnRegisterCaps += RegisterCaps; - int nworkers = 1; // was 2 + int nworkers = 2; // was 2 if (ProcessQueuedRequestsAsync && m_workerThreads == null) { m_workerThreads = new Thread[nworkers]; @@ -365,7 +365,11 @@ namespace OpenSim.Region.ClientStack.Linden requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); lock (responses) + { + if (responses.ContainsKey(requestID)) + m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054"); responses[requestID] = response; + } WebFetchInvDescModule.ProcessedRequestsCount++; } diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs index 01814a1..eb7d3a9 100644 --- a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs +++ b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs @@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library { InventoryFolderImpl folder = null; InventoryCollection inv = new InventoryCollection(); - inv.UserID = m_Library.Owner; + inv.OwnerID = m_Library.Owner; if (folderID != m_Library.ID) { @@ -87,6 +87,18 @@ namespace OpenSim.Region.CoreModules.Framework.Library return inv; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + } + /// /// Add a new folder to the user's inventory /// diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index e13ee42..232cfdf 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -389,6 +389,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return connector.GetFolderContent(userID, folderID); } + public InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs) + { + string invURL = GetInventoryServiceURL(userID); + + if (invURL == null) // not there, forward to local inventory connector to resolve + lock (m_Lock) + return m_LocalGridInventoryService.GetMultipleFoldersContent(userID, folderIDs); + + else + { + InventoryCollection[] coll = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + coll[i++] = GetFolderContent(userID, fid); + + return coll; + } + } + public List GetFolderItems(UUID userID, UUID folderID) { //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index 499ca5e..71dc337 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (m_Inventories.TryGetValue(userID, out inv)) { c = new InventoryCollection(); - c.UserID = userID; + c.OwnerID = userID; c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index cbe0e37..75dd200 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -195,6 +195,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return invCol; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + + } + public List GetFolderItems(UUID userID, UUID folderID) { return m_InventoryService.GetFolderItems(userID, folderID); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 166e4a1..9beb382 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -204,6 +204,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return invCol; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + return m_RemoteConnector.GetMultipleFoldersContent(principalID, folderIDs); + } + public List GetFolderItems(UUID userID, UUID folderID) { return m_RemoteConnector.GetFolderItems(userID, folderID); diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 0288fa6..4f01e36 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -41,7 +41,9 @@ using OpenSim.Server.Handlers.Base; using log4net; using OpenMetaverse; -namespace OpenSim.Server.Handlers.Asset +using System.Threading; + +namespace OpenSim.Server.Handlers.Inventory { public class XInventoryInConnector : ServiceConnector { @@ -123,6 +125,8 @@ namespace OpenSim.Server.Handlers.Asset return HandleGetFolderForType(request); case "GETFOLDERCONTENT": return HandleGetFolderContent(request); + case "GETMULTIPLEFOLDERSCONTENT": + return HandleGetMultipleFoldersContent(request); case "GETFOLDERITEMS": return HandleGetFolderItems(request); case "ADDFOLDER": @@ -284,6 +288,8 @@ namespace OpenSim.Server.Handlers.Asset InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID); if (icoll != null) { + result["FID"] = icoll.FolderID.ToString(); + result["VERSION"] = icoll.Version.ToString(); Dictionary folders = new Dictionary(); int i = 0; if (icoll.Folders != null) @@ -314,7 +320,71 @@ namespace OpenSim.Server.Handlers.Asset return Util.UTF8NoBomEncoding.GetBytes(xmlString); } - byte[] HandleGetFolderItems(Dictionary request) + byte[] HandleGetMultipleFoldersContent(Dictionary request) + { + Dictionary resultSet = new Dictionary(); + UUID principal = UUID.Zero; + UUID.TryParse(request["PRINCIPAL"].ToString(), out principal); + string folderIDstr = request["FOLDERS"].ToString(); + int count = 0; + Int32.TryParse(request["COUNT"].ToString(), out count); + + UUID[] fids = new UUID[count]; + string[] uuids = folderIDstr.Split(','); + int i = 0; + foreach (string id in uuids) + { + UUID fid = UUID.Zero; + if (UUID.TryParse(id, out fid)) + fids[i] = fid; + i += 1; + } + + count = 0; + InventoryCollection[] icollList = m_InventoryService.GetMultipleFoldersContent(principal, fids); + if (icollList != null && icollList.Length > 0) + { + foreach (InventoryCollection icoll in icollList) + { + Dictionary result = new Dictionary(); + result["FID"] = icoll.FolderID.ToString(); + result["VERSION"] = icoll.Version.ToString(); + result["OWNER"] = icoll.OwnerID.ToString(); + Dictionary folders = new Dictionary(); + i = 0; + if (icoll.Folders != null) + { + foreach (InventoryFolderBase f in icoll.Folders) + { + folders["folder_" + i.ToString()] = EncodeFolder(f); + i++; + } + result["FOLDERS"] = folders; + } + i = 0; + if (icoll.Items != null) + { + Dictionary items = new Dictionary(); + foreach (InventoryItemBase it in icoll.Items) + { + items["item_" + i.ToString()] = EncodeItem(it); + i++; + } + result["ITEMS"] = items; + } + + resultSet["F_" + fids[count++]] = result; + //m_log.DebugFormat("[XXX]: Sending {0} {1}", fids[count-1], icoll.FolderID); + } + } + + string xmlString = ServerUtils.BuildXmlResponse(resultSet); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + + byte[] HandleGetFolderItems(Dictionary request) { Dictionary result = new Dictionary(); UUID principal = UUID.Zero; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 574de89..c694d27 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -205,7 +205,7 @@ namespace OpenSim.Services.Connectors InventoryCollection inventory = new InventoryCollection(); inventory.Folders = new List(); inventory.Items = new List(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; try { @@ -235,7 +235,86 @@ namespace OpenSim.Services.Connectors return inventory; } + + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length]; + //m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", folderIDs.Length); + try + { + Dictionary resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT", + new Dictionary { + { "PRINCIPAL", principalID.ToString() }, + { "FOLDERS", String.Join(",", folderIDs) }, + { "COUNT", folderIDs.Length.ToString() } + }); + + if (!CheckReturn(resultSet)) + return null; + int i = 0; + foreach (KeyValuePair kvp in resultSet) + { + InventoryCollection inventory = new InventoryCollection(); + if (kvp.Key.StartsWith("F_")) + { + UUID fid = UUID.Zero; + if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i]) + { + inventory.Folders = new List(); + inventory.Items = new List(); + + Dictionary ret = (Dictionary)kvp.Value; + + if (ret.ContainsKey("FID")) + { + if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID)) + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString()); + } + else + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response"); + + inventory.Version = -1; + if (ret.ContainsKey("VERSION")) + Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version); + if (ret.ContainsKey("OWNER")) + UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID); + + //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID); + + Dictionary folders = + (Dictionary)ret["FOLDERS"]; + Dictionary items = + (Dictionary)ret["ITEMS"]; + + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + { + inventory.Folders.Add(BuildFolder((Dictionary)o)); + } + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + { + inventory.Items.Add(BuildItem((Dictionary)o)); + } + + inventoryArr[i] = inventory; + } + else + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}", + folderIDs[i], fid); + } + + i += 1; + } + } + } + catch (Exception e) + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message); + } + + return inventoryArr; + } public List GetFolderItems(UUID principalID, UUID folderID) { Dictionary ret = MakeRequest("GETFOLDERITEMS", diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 9ded1c4..0331c66 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -340,7 +340,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; + inventory.OwnerID = userID; NameValueCollection requestArgs = new NameValueCollection { @@ -371,6 +371,18 @@ namespace OpenSim.Services.Connectors.SimianGrid return inventory; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + } + /// /// Gets the items inside a folder /// @@ -380,7 +392,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public List GetFolderItems(UUID userID, UUID folderID) { InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; + inventory.OwnerID = userID; NameValueCollection requestArgs = new NameValueCollection { diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 2c63240..5f245e4 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -153,7 +153,14 @@ namespace OpenSim.Services.HypergridService //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) //{ //} - + + // NOGO + // + public override InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderID) + { + return new InventoryCollection[0]; + } + //public List GetFolderItems(UUID principalID, UUID folderID) //{ //} diff --git a/OpenSim/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs index 2805356..829f169 100644 --- a/OpenSim/Services/Interfaces/IInventoryService.cs +++ b/OpenSim/Services/Interfaces/IInventoryService.cs @@ -76,6 +76,14 @@ namespace OpenSim.Services.Interfaces /// /// Inventory content. null if the request failed. InventoryCollection GetFolderContent(UUID userID, UUID folderID); + + /// + /// Gets everything (folders and items) inside a folder + /// + /// + /// + /// Inventory content. null if the request failed. + InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs); /// /// Gets the items inside a folder diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 362ff8f..6582b75 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -291,7 +291,7 @@ namespace OpenSim.Services.InventoryService // //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; inventory.Folders = new List(); inventory.Items = new List(); @@ -315,8 +315,27 @@ namespace OpenSim.Services.InventoryService inventory.Items.Add(ConvertToOpenSim(i)); } + InventoryFolderBase f = new InventoryFolderBase(folderID, principalID); + f = GetFolder(f); + if (f != null) + { + inventory.Version = f.Version; + inventory.OwnerID = f.Owner; + } + inventory.FolderID = folderID; + return inventory; } + + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] multiple = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + multiple[i++] = GetFolderContent(principalID, fid); + + return multiple; + } public virtual List GetFolderItems(UUID principalID, UUID folderID) { -- cgit v1.1 From a68aab14fa7c23d7af938b0b6a820bad51975f44 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 8 May 2015 06:57:06 -0700 Subject: Additional debug message to help diagnose a warning message and exception related to previous commit. See http://opensimulator.org/mantis/view.php?id=7054#c28282 --- .../Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs | 3 +++ OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs | 1 + 2 files changed, 4 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index a2f6740..e4ce1f3 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -590,6 +590,9 @@ namespace OpenSim.Capabilities.Handlers // Do some post-processing. May need to fetch more from inv server for links foreach (InventoryCollection contents in fetchedContents) { + if (contents == null) + continue; + InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); coll.Collection = contents; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index c694d27..80a3df2 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -302,6 +302,7 @@ namespace OpenSim.Services.Connectors { m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}", folderIDs[i], fid); + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: ", String.Join(",", folderIDs), String.Join(",", resultSet.Keys)); } i += 1; -- cgit v1.1 From 3548e39f9a5512416edc6c7488489a94bf0d4b80 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 8 May 2015 07:36:30 -0700 Subject: I shouldn't write code this early in the morning... Fixing a 'duh' on previous commit. --- OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 80a3df2..56dece3 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -302,7 +302,7 @@ namespace OpenSim.Services.Connectors { m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}", folderIDs[i], fid); - m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: ", String.Join(",", folderIDs), String.Join(",", resultSet.Keys)); + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys)); } i += 1; -- cgit v1.1 From 3110b1661f04a501cb6a9b8173bed516211a5827 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 8 May 2015 08:37:31 -0700 Subject: Apparently Firestorm sometimes sends duplicate folder ids on the same request (see http://opensimulator.org/mantis/view.php?id=7054#c28297). This was throwing the new inventory download code off. Firestorm also sends requests for folder UUID.Zero, which doesn't exist, but doesn't cause any problems either -- it just fails. I'm leaving the warning message for now, just to keep an eye on which folders can't be found, but may remove it in the future. --- .../Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index e4ce1f3..27666f7 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -109,7 +109,9 @@ namespace OpenSim.Capabilities.Handlers continue; } - folders.Add(llsdRequest); + // Filter duplicate folder ids that bad viewers may send + if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null) + folders.Add(llsdRequest); } if (folders.Count > 0) @@ -540,6 +542,8 @@ namespace OpenSim.Capabilities.Handlers List libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); fetchFolders.RemoveAll(f => libfolders.Contains(f)); + //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count); + foreach (LLSDFetchInventoryDescendents f in libfolders) { if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) @@ -553,7 +557,7 @@ namespace OpenSim.Capabilities.Handlers ret.Collection.Version = fold.Version; ret.Descendents = ret.Collection.Items.Count; - +// m_log.DebugFormat("[XXX]: Added libfolder {0} ({1})", ret.Collection.FolderID, ret.Collection.OwnerID); result.Add(ret); } } @@ -578,6 +582,8 @@ namespace OpenSim.Capabilities.Handlers foreach (LLSDFetchInventoryDescendents f in fetchFolders) fids[i++] = f.folder_id; + //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); + InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) -- cgit v1.1 From e5cf6a29fba650ef163f325c919417c35855aa2b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 8 May 2015 17:02:02 -0700 Subject: Restore handling of bad folders. I'm not entirely sure this is part of the protocol -- I don't see it here: http://wiki.secondlife.com/wiki/Linden_Lab_Official:Inventory_API#Fetch_inventory_descendents But who knows! --- .../FetchInvDescHandler.cs | 57 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index 27666f7..b7f332d 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -116,8 +116,10 @@ namespace OpenSim.Capabilities.Handlers if (folders.Count > 0) { - List invcollSet = Fetch(folders); + List bad_folders = new List(); + List invcollSet = Fetch(folders, bad_folders); //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); + if (invcollSet == null) { m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol."); @@ -135,6 +137,10 @@ namespace OpenSim.Capabilities.Handlers response += inventoryitemstr; } + + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); + foreach (UUID bad in bad_folders) + bad_folders_response += "" + bad + ""; } if (response.Length == 0) @@ -161,8 +167,8 @@ namespace OpenSim.Capabilities.Handlers } } -// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); -// m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count); + //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response); return response; @@ -557,14 +563,15 @@ namespace OpenSim.Capabilities.Handlers ret.Collection.Version = fold.Version; ret.Descendents = ret.Collection.Items.Count; -// m_log.DebugFormat("[XXX]: Added libfolder {0} ({1})", ret.Collection.FolderID, ret.Collection.OwnerID); result.Add(ret); + + //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); } } } } - private List Fetch(List fetchFolders) + private List Fetch(List fetchFolders, List bad_folders) { //m_log.DebugFormat( // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); @@ -596,11 +603,15 @@ namespace OpenSim.Capabilities.Handlers // Do some post-processing. May need to fetch more from inv server for links foreach (InventoryCollection contents in fetchedContents) { + InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); + coll.Collection = contents; + if (contents == null) + { + bad_folders.Add(fids[i++]); continue; + } - InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); - coll.Collection = contents; // Find the original request LLSDFetchInventoryDescendents freq = fetchFolders[i++]; @@ -622,8 +633,36 @@ namespace OpenSim.Capabilities.Handlers } else { - m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); - continue; + // Was it really a request for folder Zero? + // This is an overkill, but Firestorm really asks for folder Zero. + // I'm leaving the code here for the time being, but commented. + if (fetchFolders[i - 1].folder_id == UUID.Zero) + { + //coll.Collection.OwnerID = freq.owner_id; + //coll.Collection.FolderID = contents.FolderID; + //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); + //if (containingFolder != null) + //{ + // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); + // coll.Collection.Folders.Clear(); + // coll.Collection.Folders.Add(containingFolder); + // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) + // { + // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); + // lib.Name = m_LibraryService.LibraryRootFolder.Name; + // lib.Type = m_LibraryService.LibraryRootFolder.Type; + // lib.Version = m_LibraryService.LibraryRootFolder.Version; + // coll.Collection.Folders.Add(lib); + // } + // coll.Collection.Items.Clear(); + //} + } + else + { + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); + bad_folders.Add(freq.folder_id); + continue; + } } } -- cgit v1.1 From 0bf1209f908bb9a384ddb3a4255a75bf2317c478 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 8 May 2015 20:53:28 -0700 Subject: Another major overhaul of inventory downloading, this time pertaining to inventory links. Added yet another function to IInventoryService to get multiple items at once, so that fetching collections of linked items is done once per folder instead of once per item. --- .../FetchInvDescHandler.cs | 242 ++++++++++++--------- .../Framework/Library/LocalInventoryService.cs | 16 ++ .../Inventory/HGInventoryBroker.cs | 17 ++ .../Inventory/LocalInventoryServiceConnector.cs | 5 + .../Inventory/RemoteXInventoryServiceConnector.cs | 8 + .../Handlers/Inventory/XInventoryInConnector.cs | 36 +++ .../Inventory/XInventoryServicesConnector.cs | 37 ++++ .../SimianGrid/SimianInventoryServiceConnector.cs | 15 ++ OpenSim/Services/Interfaces/IInventoryService.cs | 9 +- .../Services/InventoryService/XInventoryService.cs | 15 ++ 10 files changed, 297 insertions(+), 103 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index b7f332d..8dd6235 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -603,136 +603,174 @@ namespace OpenSim.Capabilities.Handlers // Do some post-processing. May need to fetch more from inv server for links foreach (InventoryCollection contents in fetchedContents) { + // Find the original request + LLSDFetchInventoryDescendents freq = fetchFolders[i++]; + InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); coll.Collection = contents; - if (contents == null) - { - bad_folders.Add(fids[i++]); + if (BadFolder(freq, contents, bad_folders)) continue; + + // Next: link management + ProcessLinks(freq, coll); + + result.Add(coll); + } + } + + return result; + } + + private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List bad_folders) + { + bool bad = false; + if (contents == null) + { + bad_folders.Add(freq.folder_id); + bad = true; + } + + // The inventory server isn't sending FolderID in the collection... + // Must fetch it individually + if (contents.FolderID == UUID.Zero) + { + InventoryFolderBase containingFolder = new InventoryFolderBase(); + containingFolder.ID = freq.folder_id; + containingFolder.Owner = freq.owner_id; + containingFolder = m_InventoryService.GetFolder(containingFolder); + + if (containingFolder != null) + { + contents.FolderID = containingFolder.ID; + contents.OwnerID = containingFolder.Owner; + contents.Version = containingFolder.Version; + } + else + { + // Was it really a request for folder Zero? + // This is an overkill, but Firestorm really asks for folder Zero. + // I'm leaving the code here for the time being, but commented. + if (freq.folder_id == UUID.Zero) + { + //coll.Collection.OwnerID = freq.owner_id; + //coll.Collection.FolderID = contents.FolderID; + //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); + //if (containingFolder != null) + //{ + // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); + // coll.Collection.Folders.Clear(); + // coll.Collection.Folders.Add(containingFolder); + // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) + // { + // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); + // lib.Name = m_LibraryService.LibraryRootFolder.Name; + // lib.Type = m_LibraryService.LibraryRootFolder.Type; + // lib.Version = m_LibraryService.LibraryRootFolder.Version; + // coll.Collection.Folders.Add(lib); + // } + // coll.Collection.Items.Clear(); + //} + } + else + { + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); + bad_folders.Add(freq.folder_id); + bad = true; } + } + } + return bad; + } - // Find the original request - LLSDFetchInventoryDescendents freq = fetchFolders[i++]; + private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) + { + InventoryCollection contents = coll.Collection; + + if (freq.fetch_items && contents.Items != null) + { + List itemsToReturn = contents.Items; + + // descendents must only include the links, not the linked items we add + coll.Descendents = itemsToReturn.Count; - // The inventory server isn't sending FolderID in the collection... - // Must fetch it individually - if (contents.FolderID == UUID.Zero) + // Add target items for links in this folder before the links themselves. + List itemIDs = new List(); + List folderIDs = new List(); + foreach (InventoryItemBase item in itemsToReturn) + { + //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); + if (item.AssetType == (int)AssetType.Link) + itemIDs.Add(item.AssetID); + + else if (item.AssetType == (int)AssetType.LinkFolder) + folderIDs.Add(item.AssetID); + } + + //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); + + // Scan for folder links and insert the items they target and those links at the head of the return data + if (folderIDs.Count > 0) + { + InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray()); + foreach (InventoryCollection linkedFolderContents in linkedFolders) { - InventoryFolderBase containingFolder = new InventoryFolderBase(); - containingFolder.ID = freq.folder_id; - containingFolder.Owner = freq.owner_id; - containingFolder = m_InventoryService.GetFolder(containingFolder); + List links = linkedFolderContents.Items; - if (containingFolder != null) - { - contents.FolderID = containingFolder.ID; - contents.OwnerID = containingFolder.Owner; - contents.Version = containingFolder.Version; - } - else + itemsToReturn.InsertRange(0, links); + + foreach (InventoryItemBase link in linkedFolderContents.Items) { - // Was it really a request for folder Zero? - // This is an overkill, but Firestorm really asks for folder Zero. - // I'm leaving the code here for the time being, but commented. - if (fetchFolders[i - 1].folder_id == UUID.Zero) - { - //coll.Collection.OwnerID = freq.owner_id; - //coll.Collection.FolderID = contents.FolderID; - //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); - //if (containingFolder != null) - //{ - // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); - // coll.Collection.Folders.Clear(); - // coll.Collection.Folders.Add(containingFolder); - // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) - // { - // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); - // lib.Name = m_LibraryService.LibraryRootFolder.Name; - // lib.Type = m_LibraryService.LibraryRootFolder.Type; - // lib.Version = m_LibraryService.LibraryRootFolder.Version; - // coll.Collection.Folders.Add(lib); - // } - // coll.Collection.Items.Clear(); - //} - } - else + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (link != null) { - m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); - bad_folders.Add(freq.folder_id); - continue; + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", + // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID); + itemIDs.Add(link.ID); } } } + } - if (freq.fetch_items && contents.Items != null) + if (itemIDs.Count > 0) + { + InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); + if (linked == null) { - List itemsToReturn = contents.Items; - List originalItems = new List(itemsToReturn); - - // descendents must only include the links, not the linked items we add - coll.Descendents = originalItems.Count; - - // Add target items for links in this folder before the links themselves. - foreach (InventoryItemBase item in originalItems) + // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); + linked = new InventoryItemBase[itemIDs.Count]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = freq.owner_id; + foreach (UUID id in itemIDs) { - if (item.AssetType == (int)AssetType.Link) - { - InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); - - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) - { - itemsToReturn.Insert(0, linkedItem); - } - } + item.ID = id; + linked[i++] = m_InventoryService.GetItem(item); } + } - // Now scan for folder links and insert the items they target and those links at the head of the return data - foreach (InventoryItemBase item in originalItems) + foreach (InventoryItemBase linkedItem in linked) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) { - if (item.AssetType == (int)AssetType.LinkFolder) - { - InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(coll.Collection.OwnerID, item.AssetID); - List links = linkedFolderContents.Items; - - itemsToReturn.InsertRange(0, links); - - foreach (InventoryItemBase link in linkedFolderContents.Items) - { - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (link != null) - { - //m_log.DebugFormat( - // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", - // link.Name, (AssetType)link.AssetType, item.AssetID, contents.FolderID); - - InventoryItemBase linkedItem - = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); - - if (linkedItem != null) - itemsToReturn.Insert(0, linkedItem); - } - } - } + itemsToReturn.Insert(0, linkedItem); } } - - result.Add(coll); } } - return result; } - /// /// Convert an internal inventory folder object into an LLSD object. /// diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs index eb7d3a9..e657f53 100644 --- a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs +++ b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs @@ -99,6 +99,22 @@ namespace OpenSim.Region.CoreModules.Framework.Library return invColl; } + public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) + { + InventoryItemBase[] itemColl = new InventoryItemBase[itemIDs.Length]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = principalID; + foreach (UUID fid in itemIDs) + { + item.ID = fid; + itemColl[i++] = GetItem(item); + } + + return itemColl; + } + + /// /// Add a new folder to the user's inventory /// diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 232cfdf..6a83b42 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -615,6 +615,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return connector.GetItem(item); } + public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs) + { + if (itemIDs == null) + return new InventoryItemBase[0]; + //m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID); + + string invURL = GetInventoryServiceURL(userID); + + if (invURL == null) // not there, forward to local inventory connector to resolve + lock (m_Lock) + return m_LocalGridInventoryService.GetMultipleItems(userID, itemIDs); + + IInventoryService connector = GetConnector(invURL); + + return connector.GetMultipleItems(userID, itemIDs); + } + public InventoryFolderBase GetFolder(InventoryFolderBase folder) { if (folder == null) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index 75dd200..2f29a7c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -307,6 +307,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return item; } + public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs) + { + return m_InventoryService.GetMultipleItems(userID, itemIDs); + } + public InventoryFolderBase GetFolder(InventoryFolderBase folder) { return m_InventoryService.GetFolder(folder); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 9beb382..e0cc1e8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -303,6 +303,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return m_RemoteConnector.GetItem(item); } + public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs) + { + if (itemIDs == null) + return new InventoryItemBase[0]; + + return m_RemoteConnector.GetMultipleItems(userID, itemIDs); + } + public InventoryFolderBase GetFolder(InventoryFolderBase folder) { //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID); diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 4f01e36..cf0762b 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -149,6 +149,8 @@ namespace OpenSim.Server.Handlers.Inventory return HandleDeleteItems(request); case "GETITEM": return HandleGetItem(request); + case "GETMULTIPLEITEMS": + return HandleGetMultipleItems(request); case "GETFOLDER": return HandleGetFolder(request); case "GETACTIVEGESTURES": @@ -576,6 +578,40 @@ namespace OpenSim.Server.Handlers.Inventory return Util.UTF8NoBomEncoding.GetBytes(xmlString); } + byte[] HandleGetMultipleItems(Dictionary request) + { + Dictionary resultSet = new Dictionary(); + UUID principal = UUID.Zero; + UUID.TryParse(request["PRINCIPAL"].ToString(), out principal); + string itemIDstr = request["ITEMS"].ToString(); + int count = 0; + Int32.TryParse(request["COUNT"].ToString(), out count); + + UUID[] fids = new UUID[count]; + string[] uuids = itemIDstr.Split(','); + int i = 0; + foreach (string id in uuids) + { + UUID fid = UUID.Zero; + if (UUID.TryParse(id, out fid)) + fids[i] = fid; + i += 1; + } + + InventoryItemBase[] itemsList = m_InventoryService.GetMultipleItems(principal, fids); + if (itemsList != null && itemsList.Length > 0) + { + count = 0; + foreach (InventoryItemBase item in itemsList) + resultSet["item_" + count++] = (item == null) ? (object)"NULL" : EncodeItem(item); + } + + string xmlString = ServerUtils.BuildXmlResponse(resultSet); + + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + byte[] HandleGetFolder(Dictionary request) { Dictionary result = new Dictionary(); diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 56dece3..0cea4a1 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -316,6 +316,7 @@ namespace OpenSim.Services.Connectors return inventoryArr; } + public List GetFolderItems(UUID principalID, UUID folderID) { Dictionary ret = MakeRequest("GETFOLDERITEMS", @@ -526,6 +527,42 @@ namespace OpenSim.Services.Connectors return null; } + public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) + { + InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length]; + try + { + Dictionary resultSet = MakeRequest("GETMULTIPLEITEMS", + new Dictionary { + { "PRINCIPAL", principalID.ToString() }, + { "ITEMS", String.Join(",", itemIDs) }, + { "COUNT", itemIDs.Length.ToString() } + }); + + if (!CheckReturn(resultSet)) + return null; + + int i = 0; + foreach (KeyValuePair kvp in resultSet) + { + InventoryCollection inventory = new InventoryCollection(); + if (kvp.Key.StartsWith("item_")) + { + if (kvp.Value is Dictionary) + itemArr[i++] = BuildItem((Dictionary)kvp.Value); + else + itemArr[i++] = null; + } + } + } + catch (Exception e) + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message); + } + + return itemArr; + } + public InventoryFolderBase GetFolder(InventoryFolderBase folder) { try diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index 0331c66..fdeea18 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -301,6 +301,21 @@ namespace OpenSim.Services.Connectors.SimianGrid return null; } + public InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) + { + InventoryItemBase[] result = new InventoryItemBase[itemIDs.Length]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = principalID; + foreach (UUID id in itemIDs) + { + item.ID = id; + result[i++] = GetItem(item); + } + + return result; + } + /// /// Get a folder, given by its UUID /// diff --git a/OpenSim/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs index 829f169..1e8652c 100644 --- a/OpenSim/Services/Interfaces/IInventoryService.cs +++ b/OpenSim/Services/Interfaces/IInventoryService.cs @@ -82,7 +82,7 @@ namespace OpenSim.Services.Interfaces /// /// /// - /// Inventory content. null if the request failed. + /// Inventory content. InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs); /// @@ -164,6 +164,13 @@ namespace OpenSim.Services.Interfaces InventoryItemBase GetItem(InventoryItemBase item); /// + /// Get multiple items, given by their UUIDs + /// + /// + /// null if no item was found, otherwise the found item + InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] ids); + + /// /// Get a folder, given by its UUID /// /// diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 6582b75..50cadab 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -610,6 +610,21 @@ namespace OpenSim.Services.InventoryService return ConvertToOpenSim(items[0]); } + public virtual InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] ids) + { + InventoryItemBase[] items = new InventoryItemBase[ids.Length]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = userID; + foreach (UUID id in ids) + { + item.ID = id; + items[i++] = GetItem(item); + } + + return items; + } + public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder) { XInventoryFolder[] folders = m_Database.GetFolders( -- cgit v1.1 From adf0f49a697353184201b5dc80e6af332f29d55f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 9 May 2015 08:58:59 -0700 Subject: Fix mantis #7054: AO in Firestorm and Kokua stopped loading after new inventory code in place. Cause: # of descendants was wrong. --- .../FetchInvDescHandler.cs | 26 ++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs index 8dd6235..810096f 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs @@ -676,8 +676,8 @@ namespace OpenSim.Capabilities.Handlers { m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); bad_folders.Add(freq.folder_id); - bad = true; } + bad = true; } } @@ -755,15 +755,23 @@ namespace OpenSim.Capabilities.Handlers } } - foreach (InventoryItemBase linkedItem in linked) + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id); + //foreach (InventoryItemBase item in itemsToReturn) + // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder); + + if (linked != null) { - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) + foreach (InventoryItemBase linkedItem in linked) { - itemsToReturn.Insert(0, linkedItem); + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) + { + itemsToReturn.Insert(0, linkedItem); + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); + } } } } @@ -824,7 +832,7 @@ namespace OpenSim.Capabilities.Handlers } } - struct InventoryCollectionWithDescendents + class InventoryCollectionWithDescendents { public InventoryCollection Collection; public int Descendents; -- cgit v1.1 From f20728fc86accb4df56024e587e8d5762a8dda34 Mon Sep 17 00:00:00 2001 From: Dev Random Date: Sat, 9 May 2015 15:26:34 -0400 Subject: Constrain 'terrain modify' to selected Region Signed-off-by: Michael Cerquoni --- .../CoreModules/World/Terrain/TerrainModule.cs | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 05c5fca..cec17e2 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -551,11 +551,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_plugineffects = new Dictionary(); LoadPlugins(Assembly.GetCallingAssembly()); string plugineffectsPath = "Terrain"; - + // Load the files in the Terrain/ dir if (!Directory.Exists(plugineffectsPath)) return; - + string[] files = Directory.GetFiles(plugineffectsPath); foreach(string file in files) { @@ -768,7 +768,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain fileStartX, fileStartY, fileStartX + fileWidth - 1, fileStartY + fileHeight - 1, m_scene.RegionInfo.RegionName, filename); } - + return; } } @@ -865,7 +865,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain client.OnLandUndo += client_OnLandUndo; client.OnUnackedTerrain += client_OnUnackedTerrain; } - + /// /// Installs terrain brush hook to IClientAPI /// @@ -884,7 +884,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain lock(m_perClientPatchUpdates) m_perClientPatchUpdates.Remove(client); } - + /// /// Scan over changes in the terrain and limit height changes. This enforces the /// non-estate owner limits on rate of terrain editting. @@ -1225,7 +1225,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain InterfaceBakeTerrain(null); //bake terrain does not use the passed in parameter } } - + protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY) { //m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY); @@ -1676,10 +1676,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain public void ModifyCommand(string module, string[] cmd) { string result; - if (cmd.Length > 2) + Scene scene = SceneManager.Instance.CurrentScene; + if ((scene != null) && (scene != m_scene)) + { + result = String.Empty; + } + else if (cmd.Length > 2) { string operationType = cmd[2]; + ITerrainModifier operation; if (!m_modifyOperations.TryGetValue(operationType, out operation)) { @@ -1704,7 +1710,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain { result = "Usage: ..."; } - MainConsole.Instance.Output(result); + if (result != String.Empty) + { + MainConsole.Instance.Output(result); + } } #endregion -- cgit v1.1 From f992ed0f400573a54cca0dc919284f88ae83540f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 08:44:21 -0700 Subject: Added unit tests for FetchInventoryDescendents http://wiki.secondlife.com/wiki/Linden_Lab_Official:Inventory_API#Fetch_Inventory_Descendents Also, consolidated the location of the files that handle inventory capabilities. --- .../Handlers/FetchInventory/FetchInvDescHandler.cs | 840 +++++++++++++++++++++ .../FetchInventory/FetchInvDescServerConnector.cs | 82 ++ .../FetchInventory/FetchInventory2Handler.cs | 118 +++ .../FetchInventoryDescendents2HandlerTests.cs | 217 ++++++ .../FetchInventory2/FetchInventory2Handler.cs | 118 --- .../FetchInvDescHandler.cs | 840 --------------------- .../FetchInvDescServerConnector.cs | 82 -- 7 files changed, 1257 insertions(+), 1040 deletions(-) create mode 100644 OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs create mode 100644 OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs create mode 100644 OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs create mode 100644 OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs delete mode 100644 OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs delete mode 100644 OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs delete mode 100644 OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs new file mode 100644 index 0000000..810096f --- /dev/null +++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs @@ -0,0 +1,840 @@ +/* + * 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 System.Collections; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Capabilities.Handlers +{ + public class FetchInvDescHandler + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IInventoryService m_InventoryService; + private ILibraryService m_LibraryService; +// private object m_fetchLock = new Object(); + + public FetchInvDescHandler(IInventoryService invService, ILibraryService libService) + { + m_InventoryService = invService; + m_LibraryService = libService; + } + + + public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + + // nasty temporary hack here, the linden client falsely + // identifies the uuid 00000000-0000-0000-0000-000000000000 + // as a string which breaks us + // + // correctly mark it as a uuid + // + request = request.Replace("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000"); + + // another hack 1 results in a + // System.ArgumentException: Object type System.Int32 cannot + // be converted to target type: System.Boolean + // + request = request.Replace("fetch_folders0", "fetch_folders0"); + request = request.Replace("fetch_folders1", "fetch_folders1"); + + Hashtable hash = new Hashtable(); + try + { + hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); + } + catch (LLSD.LLSDParseException e) + { + m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); + m_log.Error("Request: " + request); + } + + ArrayList foldersrequested = (ArrayList)hash["folders"]; + + string response = ""; + string bad_folders_response = ""; + + List folders = new List(); + for (int i = 0; i < foldersrequested.Count; i++) + { + Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + + LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + + try + { + LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); + } + catch (Exception e) + { + m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); + continue; + } + + // Filter duplicate folder ids that bad viewers may send + if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null) + folders.Add(llsdRequest); + } + + if (folders.Count > 0) + { + List bad_folders = new List(); + List invcollSet = Fetch(folders, bad_folders); + //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); + + if (invcollSet == null) + { + m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol."); + return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse); + } + + string inventoryitemstr = string.Empty; + foreach (InventoryCollectionWithDescendents icoll in invcollSet) + { + LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents); + + inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); + inventoryitemstr = inventoryitemstr.Replace("folders", ""); + inventoryitemstr = inventoryitemstr.Replace("", ""); + + response += inventoryitemstr; + } + + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); + foreach (UUID bad in bad_folders) + bad_folders_response += "" + bad + ""; + } + + if (response.Length == 0) + { + /* Viewers expect a bad_folders array when not available */ + if (bad_folders_response.Length != 0) + { + response = "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders"; + } + } + else + { + if (bad_folders_response.Length != 0) + { + response = "folders" + response + "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders" + response + ""; + } + } + + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count); + //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response); + + return response; + + } + + /// + /// Construct an LLSD reply packet to a CAPS inventory request + /// + /// + /// + private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) + { + LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); + LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); + contents.agent_id = invFetch.owner_id; + contents.owner_id = invFetch.owner_id; + contents.folder_id = invFetch.folder_id; + + reply.folders.Array.Add(contents); + InventoryCollection inv = new InventoryCollection(); + inv.Folders = new List(); + inv.Items = new List(); + int version = 0; + int descendents = 0; + + inv + = Fetch( + invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, + invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents); + + if (inv != null && inv.Folders != null) + { + foreach (InventoryFolderBase invFolder in inv.Folders) + { + contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); + } + + descendents += inv.Folders.Count; + } + + if (inv != null && inv.Items != null) + { + foreach (InventoryItemBase invItem in inv.Items) + { + contents.items.Array.Add(ConvertInventoryItem(invItem)); + } + } + + contents.descendents = descendents; + contents.version = version; + + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", + // invFetch.folder_id, + // invFetch.fetch_items, + // invFetch.fetch_folders, + // contents.items.Array.Count, + // contents.categories.Array.Count, + // invFetch.owner_id); + + return reply; + } + + private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) + { + LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); + LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); + contents.agent_id = inv.OwnerID; + contents.owner_id = inv.OwnerID; + contents.folder_id = inv.FolderID; + + reply.folders.Array.Add(contents); + + if (inv.Folders != null) + { + foreach (InventoryFolderBase invFolder in inv.Folders) + { + contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); + } + + descendents += inv.Folders.Count; + } + + if (inv.Items != null) + { + foreach (InventoryItemBase invItem in inv.Items) + { + contents.items.Array.Add(ConvertInventoryItem(invItem)); + } + } + + contents.descendents = descendents; + contents.version = inv.Version; + + return reply; + } + /// + /// Old style. Soon to be deprecated. + /// + /// + /// + /// + /// + [Obsolete] + private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count); + + string response = ""; + string bad_folders_response = ""; + + for (int i = 0; i < foldersrequested.Count; i++) + { + string inventoryitemstr = ""; + Hashtable inventoryhash = (Hashtable)foldersrequested[i]; + + LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); + + try + { + LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); + } + catch (Exception e) + { + m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); + } + + LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); + + if (null == reply) + { + bad_folders_response += "" + llsdRequest.folder_id.ToString() + ""; + } + else + { + inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); + inventoryitemstr = inventoryitemstr.Replace("folders", ""); + inventoryitemstr = inventoryitemstr.Replace("", ""); + } + + response += inventoryitemstr; + } + + if (response.Length == 0) + { + /* Viewers expect a bad_folders array when not available */ + if (bad_folders_response.Length != 0) + { + response = "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders"; + } + } + else + { + if (bad_folders_response.Length != 0) + { + response = "folders" + response + "bad_folders" + bad_folders_response + ""; + } + else + { + response = "folders" + response + ""; + } + } + + // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); + //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); + + return response; + + // } + } + + /// + /// Handle the caps inventory descendents fetch. + /// + /// + /// + /// + /// + /// + /// + /// + /// An empty InventoryCollection if the inventory look up failed + [Obsolete] + private InventoryCollection Fetch( + UUID agentID, UUID folderID, UUID ownerID, + bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", + // fetchFolders, fetchItems, folderID, agentID); + + // FIXME MAYBE: We're not handling sortOrder! + + version = 0; + descendents = 0; + + InventoryFolderImpl fold; + if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner) + { + if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null) + { + InventoryCollection ret = new InventoryCollection(); + ret.Folders = new List(); + ret.Items = fold.RequestListOfItems(); + descendents = ret.Folders.Count + ret.Items.Count; + + return ret; + } + } + + InventoryCollection contents = new InventoryCollection(); + + if (folderID != UUID.Zero) + { + InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID); + + if (fetchedContents == null) + { + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID); + return contents; + } + contents = fetchedContents; + InventoryFolderBase containingFolder = new InventoryFolderBase(); + containingFolder.ID = folderID; + containingFolder.Owner = agentID; + containingFolder = m_InventoryService.GetFolder(containingFolder); + + if (containingFolder != null) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", + // containingFolder.Name, containingFolder.ID, agentID); + + version = containingFolder.Version; + + if (fetchItems) + { + List itemsToReturn = contents.Items; + List originalItems = new List(itemsToReturn); + + // descendents must only include the links, not the linked items we add + descendents = originalItems.Count; + + // Add target items for links in this folder before the links themselves. + foreach (InventoryItemBase item in originalItems) + { + if (item.AssetType == (int)AssetType.Link) + { + InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); + + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) + itemsToReturn.Insert(0, linkedItem); + } + } + + // Now scan for folder links and insert the items they target and those links at the head of the return data + foreach (InventoryItemBase item in originalItems) + { + if (item.AssetType == (int)AssetType.LinkFolder) + { + InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID); + List links = linkedFolderContents.Items; + + itemsToReturn.InsertRange(0, links); + + foreach (InventoryItemBase link in linkedFolderContents.Items) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (link != null) + { +// m_log.DebugFormat( +// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", +// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name); + + InventoryItemBase linkedItem + = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); + + if (linkedItem != null) + itemsToReturn.Insert(0, linkedItem); + } + } + } + } + } + +// foreach (InventoryItemBase item in contents.Items) +// { +// m_log.DebugFormat( +// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}", +// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID); +// } + + // ===== + +// +// foreach (InventoryItemBase linkedItem in linkedItemsToAdd) +// { +// m_log.DebugFormat( +// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}", +// linkedItem.Name, folderID, agentID); +// +// contents.Items.Add(linkedItem); +// } +// +// // If the folder requested contains links, then we need to send those folders first, otherwise the links +// // will be broken in the viewer. +// HashSet linkedItemFolderIdsToSend = new HashSet(); +// foreach (InventoryItemBase item in contents.Items) +// { +// if (item.AssetType == (int)AssetType.Link) +// { +// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); +// +// // Take care of genuinely broken links where the target doesn't exist +// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, +// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles +// // rather than having to keep track of every folder requested in the recursion. +// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) +// { +// // We don't need to send the folder if source and destination of the link are in the same +// // folder. +// if (linkedItem.Folder != containingFolder.ID) +// linkedItemFolderIdsToSend.Add(linkedItem.Folder); +// } +// } +// } +// +// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend) +// { +// m_log.DebugFormat( +// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}", +// linkedItemFolderId, folderID, agentID); +// +// int dummyVersion; +// InventoryCollection linkedCollection +// = Fetch( +// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion); +// +// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId); +// linkedFolder.Owner = agentID; +// linkedFolder = m_InventoryService.GetFolder(linkedFolder); +// +//// contents.Folders.AddRange(linkedCollection.Folders); +// +// contents.Folders.Add(linkedFolder); +// contents.Items.AddRange(linkedCollection.Items); +// } +// } + } + } + else + { + // Lost items don't really need a version + version = 1; + } + + return contents; + + } + + private void AddLibraryFolders(List fetchFolders, List result) + { + InventoryFolderImpl fold; + if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) + { + List libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); + fetchFolders.RemoveAll(f => libfolders.Contains(f)); + + //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count); + + foreach (LLSDFetchInventoryDescendents f in libfolders) + { + if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) + { + InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); + ret.Collection = new InventoryCollection(); + ret.Collection.Folders = new List(); + ret.Collection.Items = fold.RequestListOfItems(); + ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; + ret.Collection.FolderID = f.folder_id; + ret.Collection.Version = fold.Version; + + ret.Descendents = ret.Collection.Items.Count; + result.Add(ret); + + //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); + } + } + } + } + + private List Fetch(List fetchFolders, List bad_folders) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); + + // FIXME MAYBE: We're not handling sortOrder! + + List result = new List(); + + AddLibraryFolders(fetchFolders, result); + + if (fetchFolders.Count > 0) + { + UUID[] fids = new UUID[fetchFolders.Count]; + int i = 0; + foreach (LLSDFetchInventoryDescendents f in fetchFolders) + fids[i++] = f.folder_id; + + //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); + + InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); + + if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) + { + //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); + return null; + } + + i = 0; + // Do some post-processing. May need to fetch more from inv server for links + foreach (InventoryCollection contents in fetchedContents) + { + // Find the original request + LLSDFetchInventoryDescendents freq = fetchFolders[i++]; + + InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); + coll.Collection = contents; + + if (BadFolder(freq, contents, bad_folders)) + continue; + + // Next: link management + ProcessLinks(freq, coll); + + result.Add(coll); + } + } + + return result; + } + + private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List bad_folders) + { + bool bad = false; + if (contents == null) + { + bad_folders.Add(freq.folder_id); + bad = true; + } + + // The inventory server isn't sending FolderID in the collection... + // Must fetch it individually + if (contents.FolderID == UUID.Zero) + { + InventoryFolderBase containingFolder = new InventoryFolderBase(); + containingFolder.ID = freq.folder_id; + containingFolder.Owner = freq.owner_id; + containingFolder = m_InventoryService.GetFolder(containingFolder); + + if (containingFolder != null) + { + contents.FolderID = containingFolder.ID; + contents.OwnerID = containingFolder.Owner; + contents.Version = containingFolder.Version; + } + else + { + // Was it really a request for folder Zero? + // This is an overkill, but Firestorm really asks for folder Zero. + // I'm leaving the code here for the time being, but commented. + if (freq.folder_id == UUID.Zero) + { + //coll.Collection.OwnerID = freq.owner_id; + //coll.Collection.FolderID = contents.FolderID; + //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); + //if (containingFolder != null) + //{ + // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); + // coll.Collection.Folders.Clear(); + // coll.Collection.Folders.Add(containingFolder); + // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) + // { + // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); + // lib.Name = m_LibraryService.LibraryRootFolder.Name; + // lib.Type = m_LibraryService.LibraryRootFolder.Type; + // lib.Version = m_LibraryService.LibraryRootFolder.Version; + // coll.Collection.Folders.Add(lib); + // } + // coll.Collection.Items.Clear(); + //} + } + else + { + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); + bad_folders.Add(freq.folder_id); + } + bad = true; + } + } + + return bad; + } + + private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) + { + InventoryCollection contents = coll.Collection; + + if (freq.fetch_items && contents.Items != null) + { + List itemsToReturn = contents.Items; + + // descendents must only include the links, not the linked items we add + coll.Descendents = itemsToReturn.Count; + + // Add target items for links in this folder before the links themselves. + List itemIDs = new List(); + List folderIDs = new List(); + foreach (InventoryItemBase item in itemsToReturn) + { + //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); + if (item.AssetType == (int)AssetType.Link) + itemIDs.Add(item.AssetID); + + else if (item.AssetType == (int)AssetType.LinkFolder) + folderIDs.Add(item.AssetID); + } + + //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); + + // Scan for folder links and insert the items they target and those links at the head of the return data + if (folderIDs.Count > 0) + { + InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray()); + foreach (InventoryCollection linkedFolderContents in linkedFolders) + { + List links = linkedFolderContents.Items; + + itemsToReturn.InsertRange(0, links); + + foreach (InventoryItemBase link in linkedFolderContents.Items) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (link != null) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", + // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID); + itemIDs.Add(link.ID); + } + } + } + } + + if (itemIDs.Count > 0) + { + InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); + if (linked == null) + { + // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated + m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); + linked = new InventoryItemBase[itemIDs.Count]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = freq.owner_id; + foreach (UUID id in itemIDs) + { + item.ID = id; + linked[i++] = m_InventoryService.GetItem(item); + } + } + + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id); + //foreach (InventoryItemBase item in itemsToReturn) + // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder); + + if (linked != null) + { + foreach (InventoryItemBase linkedItem in linked) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) + { + itemsToReturn.Insert(0, linkedItem); + //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); + } + } + } + } + } + + } + + /// + /// Convert an internal inventory folder object into an LLSD object. + /// + /// + /// + private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder) + { + LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder(); + llsdFolder.folder_id = invFolder.ID; + llsdFolder.parent_id = invFolder.ParentID; + llsdFolder.name = invFolder.Name; + llsdFolder.type = invFolder.Type; + llsdFolder.preferred_type = -1; + + return llsdFolder; + } + + /// + /// Convert an internal inventory item object into an LLSD object. + /// + /// + /// + private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) + { + LLSDInventoryItem llsdItem = new LLSDInventoryItem(); + llsdItem.asset_id = invItem.AssetID; + llsdItem.created_at = invItem.CreationDate; + llsdItem.desc = invItem.Description; + llsdItem.flags = (int)invItem.Flags; + llsdItem.item_id = invItem.ID; + llsdItem.name = invItem.Name; + llsdItem.parent_id = invItem.Folder; + llsdItem.type = invItem.AssetType; + llsdItem.inv_type = invItem.InvType; + + llsdItem.permissions = new LLSDPermissions(); + llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; + llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; + llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; + llsdItem.permissions.group_id = invItem.GroupID; + llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; + llsdItem.permissions.is_owner_group = invItem.GroupOwned; + llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; + llsdItem.permissions.owner_id = invItem.Owner; + llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; + llsdItem.sale_info = new LLSDSaleInfo(); + llsdItem.sale_info.sale_price = invItem.SalePrice; + llsdItem.sale_info.sale_type = invItem.SaleType; + + return llsdItem; + } + } + + class InventoryCollectionWithDescendents + { + public InventoryCollection Collection; + public int Descendents; + } +} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs new file mode 100644 index 0000000..6fbe173 --- /dev/null +++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs @@ -0,0 +1,82 @@ +/* + * 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 Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using OpenMetaverse; + +namespace OpenSim.Capabilities.Handlers +{ + public class FetchInvDescServerConnector : ServiceConnector + { + private IInventoryService m_InventoryService; + private ILibraryService m_LibraryService; + private string m_ConfigName = "CapsService"; + + public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + if (configName != String.Empty) + m_ConfigName = configName; + + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); + + string invService = serverConfig.GetString("InventoryService", String.Empty); + + if (invService == String.Empty) + throw new Exception("No InventoryService in config file"); + + Object[] args = new Object[] { config }; + m_InventoryService = + ServerUtils.LoadPlugin(invService, args); + + if (m_InventoryService == null) + throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); + + string libService = serverConfig.GetString("LibraryService", String.Empty); + m_LibraryService = + ServerUtils.LoadPlugin(libService, args); + + FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService); + IRequestHandler reqHandler + = new RestStreamHandler( + "POST", + "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, + webFetchHandler.FetchInventoryDescendentsRequest, + "FetchInvDescendents", + null); + server.AddStreamHandler(reqHandler); + } + + } +} diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs new file mode 100644 index 0000000..b67b326 --- /dev/null +++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs @@ -0,0 +1,118 @@ +/* + * 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 OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Services.Interfaces; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; + +namespace OpenSim.Capabilities.Handlers +{ + public class FetchInventory2Handler + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IInventoryService m_inventoryService; + private UUID m_agentID; + + public FetchInventory2Handler(IInventoryService invService, UUID agentId) + { + m_inventoryService = invService; + m_agentID = agentId; + } + + public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { +// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); + + OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); + OSDArray itemsRequested = (OSDArray)requestmap["items"]; + + string reply; + LLSDFetchInventory llsdReply = new LLSDFetchInventory(); + + foreach (OSDMap osdItemId in itemsRequested) + { + UUID itemId = osdItemId["item_id"].AsUUID(); + + InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId, m_agentID)); + + if (item != null) + { + // We don't know the agent that this request belongs to so we'll use the agent id of the item + // which will be the same for all items. + llsdReply.agent_id = item.Owner; + + llsdReply.items.Array.Add(ConvertInventoryItem(item)); + } + } + + reply = LLSDHelpers.SerialiseLLSDReply(llsdReply); + + return reply; + } + + /// + /// Convert an internal inventory item object into an LLSD object. + /// + /// + /// + private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) + { + LLSDInventoryItem llsdItem = new LLSDInventoryItem(); + llsdItem.asset_id = invItem.AssetID; + llsdItem.created_at = invItem.CreationDate; + llsdItem.desc = invItem.Description; + llsdItem.flags = (int)invItem.Flags; + llsdItem.item_id = invItem.ID; + llsdItem.name = invItem.Name; + llsdItem.parent_id = invItem.Folder; + llsdItem.type = invItem.AssetType; + llsdItem.inv_type = invItem.InvType; + + llsdItem.permissions = new LLSDPermissions(); + llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; + llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; + llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; + llsdItem.permissions.group_id = invItem.GroupID; + llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; + llsdItem.permissions.is_owner_group = invItem.GroupOwned; + llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; + llsdItem.permissions.owner_id = invItem.Owner; + llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; + llsdItem.sale_info = new LLSDSaleInfo(); + llsdItem.sale_info.sale_price = invItem.SalePrice; + llsdItem.sale_info.sale_type = invItem.SaleType; + + return llsdItem; + } + } +} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs new file mode 100644 index 0000000..1064c7b --- /dev/null +++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs @@ -0,0 +1,217 @@ +/* + * 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 System.Collections.Generic; +using System.Linq; +using System.Net; +using log4net; +using log4net.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Capabilities.Handlers; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; + +namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests +{ + [TestFixture] + public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase + { + private UUID m_userID = UUID.Zero; + private Scene m_scene; + private UUID m_rootFolderID; + private int m_rootDescendents; + private UUID m_notecardsFolder; + private UUID m_objectsFolder; + + private void Init() + { + // CreateInventoryFolder an inventory + + m_scene = new SceneHelpers().SetupScene(); + + m_scene.InventoryService.CreateUserInventory(m_userID); + + m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID; + + InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Object); + m_objectsFolder = of.ID; + + // Add an object + InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID); + item.AssetID = UUID.Random(); + item.AssetType = (int)AssetType.Object; + item.Folder = m_objectsFolder; + item.Name = "Some Object"; + m_scene.InventoryService.AddItem(item); + + InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Notecard); + m_notecardsFolder = ncf.ID; + + // Add a notecard + item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID); + item.AssetID = UUID.Random(); + item.AssetType = (int)AssetType.Notecard; + item.Folder = m_notecardsFolder; + item.Name = "Test Notecard 1"; + m_scene.InventoryService.AddItem(item); + // Add another notecard + item.ID = new UUID("20000000-0000-0000-0000-000000000002"); + item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a"); + item.Name = "Test Notecard 2"; + m_scene.InventoryService.AddItem(item); + + // Add a folder + InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID); + m_scene.InventoryService.AddFolder(folder); + + // Add a link to notecard 2 in Test Folder + item.AssetID = item.ID; // use item ID of notecard 2 + item.ID = new UUID("40000000-0000-0000-0000-000000000004"); + item.AssetType = (int)AssetType.Link; + item.Folder = folder.ID; + item.Name = "Link to notecard"; + m_scene.InventoryService.AddItem(item); + + // Add a link to the Objects folder in Test Folder + item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Object).ID; // use item ID of Objects folder + item.ID = new UUID("50000000-0000-0000-0000-000000000005"); + item.AssetType = (int)AssetType.LinkFolder; + item.Folder = folder.ID; + item.Name = "Link to Objects folder"; + m_scene.InventoryService.AddItem(item); + + InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID); + m_rootDescendents = coll.Items.Count + coll.Folders.Count; + Console.WriteLine("Number of descendents: " + m_rootDescendents); + } + + [Test] + public void Test_001_SimpleFolder() + { + TestHelpers.InMethod(); + + Init(); + + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + TestOSHttpRequest req = new TestOSHttpRequest(); + TestOSHttpResponse resp = new TestOSHttpResponse(); + + string request = "foldersfetch_folders1fetch_items1folder_id"; + request += m_rootFolderID; + request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; + + string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); + + Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); + Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); + Assert.That(llsdresponse.Contains("00000000-0000-0000-0000-000000000000"), Is.True, "Response should contain userID"); + + string descendents = "descendents" + m_rootDescendents + ""; + Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents"); + Console.WriteLine(llsdresponse); + } + + [Test] + public void Test_002_MultipleFolders() + { + TestHelpers.InMethod(); + + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + TestOSHttpRequest req = new TestOSHttpRequest(); + TestOSHttpResponse resp = new TestOSHttpResponse(); + + string request = "folders"; + request += "fetch_folders1fetch_items1folder_id"; + request += m_rootFolderID; + request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; + request += "fetch_folders1fetch_items1folder_id"; + request += m_notecardsFolder; + request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; + request += ""; + + string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); + Console.WriteLine(llsdresponse); + + string descendents = "descendents" + m_rootDescendents + ""; + Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder"); + descendents = "descendents2"; + Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder"); + + Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response"); + Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response"); + } + + [Test] + public void Test_003_Links() + { + TestHelpers.InMethod(); + + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + TestOSHttpRequest req = new TestOSHttpRequest(); + TestOSHttpResponse resp = new TestOSHttpResponse(); + + string request = "foldersfetch_folders1fetch_items1folder_id"; + request += "f0000000-0000-0000-0000-00000000000f"; + request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; + + string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); + Console.WriteLine(llsdresponse); + + string descendents = "descendents2"; + Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder"); + + // Make sure that the note card link is included + Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing"); + + //Make sure the notecard item itself is included + Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing"); + + // Make sure that the source item is before the link item + int pos1 = llsdresponse.IndexOf("Test Notecard 2"); + int pos2 = llsdresponse.IndexOf("Link to notecard"); + Assert.Less(pos1, pos2, "Source of link is after link"); + + // Make sure the folder link is included + Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing"); + + // Make sure the objects inside the Objects folder are included + // Note: I'm not entirely sure this is needed, but that's what I found in the implementation + Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing"); + + // Make sure that the source item is before the link item + pos1 = llsdresponse.IndexOf("Some Object"); + pos2 = llsdresponse.IndexOf("Link to Objects folder"); + Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link"); + } + } + +} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs deleted file mode 100644 index b67b326..0000000 --- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Framework.Capabilities; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Services.Interfaces; -using OSDArray = OpenMetaverse.StructuredData.OSDArray; -using OSDMap = OpenMetaverse.StructuredData.OSDMap; - -namespace OpenSim.Capabilities.Handlers -{ - public class FetchInventory2Handler - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private IInventoryService m_inventoryService; - private UUID m_agentID; - - public FetchInventory2Handler(IInventoryService invService, UUID agentId) - { - m_inventoryService = invService; - m_agentID = agentId; - } - - public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) - { -// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); - - OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); - OSDArray itemsRequested = (OSDArray)requestmap["items"]; - - string reply; - LLSDFetchInventory llsdReply = new LLSDFetchInventory(); - - foreach (OSDMap osdItemId in itemsRequested) - { - UUID itemId = osdItemId["item_id"].AsUUID(); - - InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId, m_agentID)); - - if (item != null) - { - // We don't know the agent that this request belongs to so we'll use the agent id of the item - // which will be the same for all items. - llsdReply.agent_id = item.Owner; - - llsdReply.items.Array.Add(ConvertInventoryItem(item)); - } - } - - reply = LLSDHelpers.SerialiseLLSDReply(llsdReply); - - return reply; - } - - /// - /// Convert an internal inventory item object into an LLSD object. - /// - /// - /// - private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) - { - LLSDInventoryItem llsdItem = new LLSDInventoryItem(); - llsdItem.asset_id = invItem.AssetID; - llsdItem.created_at = invItem.CreationDate; - llsdItem.desc = invItem.Description; - llsdItem.flags = (int)invItem.Flags; - llsdItem.item_id = invItem.ID; - llsdItem.name = invItem.Name; - llsdItem.parent_id = invItem.Folder; - llsdItem.type = invItem.AssetType; - llsdItem.inv_type = invItem.InvType; - - llsdItem.permissions = new LLSDPermissions(); - llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; - llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; - llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; - llsdItem.permissions.group_id = invItem.GroupID; - llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; - llsdItem.permissions.is_owner_group = invItem.GroupOwned; - llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; - llsdItem.permissions.owner_id = invItem.Owner; - llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; - llsdItem.sale_info = new LLSDSaleInfo(); - llsdItem.sale_info.sale_price = invItem.SalePrice; - llsdItem.sale_info.sale_type = invItem.SaleType; - - return llsdItem; - } - } -} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs deleted file mode 100644 index 810096f..0000000 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs +++ /dev/null @@ -1,840 +0,0 @@ -/* - * 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 System.Collections; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Framework.Capabilities; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Services.Interfaces; -using Caps = OpenSim.Framework.Capabilities.Caps; - -namespace OpenSim.Capabilities.Handlers -{ - public class FetchInvDescHandler - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private IInventoryService m_InventoryService; - private ILibraryService m_LibraryService; -// private object m_fetchLock = new Object(); - - public FetchInvDescHandler(IInventoryService invService, ILibraryService libService) - { - m_InventoryService = invService; - m_LibraryService = libService; - } - - - public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) - { - - // nasty temporary hack here, the linden client falsely - // identifies the uuid 00000000-0000-0000-0000-000000000000 - // as a string which breaks us - // - // correctly mark it as a uuid - // - request = request.Replace("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000"); - - // another hack 1 results in a - // System.ArgumentException: Object type System.Int32 cannot - // be converted to target type: System.Boolean - // - request = request.Replace("fetch_folders0", "fetch_folders0"); - request = request.Replace("fetch_folders1", "fetch_folders1"); - - Hashtable hash = new Hashtable(); - try - { - hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); - } - catch (LLSD.LLSDParseException e) - { - m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace); - m_log.Error("Request: " + request); - } - - ArrayList foldersrequested = (ArrayList)hash["folders"]; - - string response = ""; - string bad_folders_response = ""; - - List folders = new List(); - for (int i = 0; i < foldersrequested.Count; i++) - { - Hashtable inventoryhash = (Hashtable)foldersrequested[i]; - - LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); - - try - { - LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); - } - catch (Exception e) - { - m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); - continue; - } - - // Filter duplicate folder ids that bad viewers may send - if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null) - folders.Add(llsdRequest); - } - - if (folders.Count > 0) - { - List bad_folders = new List(); - List invcollSet = Fetch(folders, bad_folders); - //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); - - if (invcollSet == null) - { - m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol."); - return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse); - } - - string inventoryitemstr = string.Empty; - foreach (InventoryCollectionWithDescendents icoll in invcollSet) - { - LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents); - - inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); - inventoryitemstr = inventoryitemstr.Replace("folders", ""); - inventoryitemstr = inventoryitemstr.Replace("", ""); - - response += inventoryitemstr; - } - - //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); - foreach (UUID bad in bad_folders) - bad_folders_response += "" + bad + ""; - } - - if (response.Length == 0) - { - /* Viewers expect a bad_folders array when not available */ - if (bad_folders_response.Length != 0) - { - response = "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders"; - } - } - else - { - if (bad_folders_response.Length != 0) - { - response = "folders" + response + "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders" + response + ""; - } - } - - //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count); - //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response); - - return response; - - } - - /// - /// Construct an LLSD reply packet to a CAPS inventory request - /// - /// - /// - private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) - { - LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); - LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); - contents.agent_id = invFetch.owner_id; - contents.owner_id = invFetch.owner_id; - contents.folder_id = invFetch.folder_id; - - reply.folders.Array.Add(contents); - InventoryCollection inv = new InventoryCollection(); - inv.Folders = new List(); - inv.Items = new List(); - int version = 0; - int descendents = 0; - - inv - = Fetch( - invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, - invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents); - - if (inv != null && inv.Folders != null) - { - foreach (InventoryFolderBase invFolder in inv.Folders) - { - contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); - } - - descendents += inv.Folders.Count; - } - - if (inv != null && inv.Items != null) - { - foreach (InventoryItemBase invItem in inv.Items) - { - contents.items.Array.Add(ConvertInventoryItem(invItem)); - } - } - - contents.descendents = descendents; - contents.version = version; - - //m_log.DebugFormat( - // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", - // invFetch.folder_id, - // invFetch.fetch_items, - // invFetch.fetch_folders, - // contents.items.Array.Count, - // contents.categories.Array.Count, - // invFetch.owner_id); - - return reply; - } - - private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) - { - LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); - LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); - contents.agent_id = inv.OwnerID; - contents.owner_id = inv.OwnerID; - contents.folder_id = inv.FolderID; - - reply.folders.Array.Add(contents); - - if (inv.Folders != null) - { - foreach (InventoryFolderBase invFolder in inv.Folders) - { - contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); - } - - descendents += inv.Folders.Count; - } - - if (inv.Items != null) - { - foreach (InventoryItemBase invItem in inv.Items) - { - contents.items.Array.Add(ConvertInventoryItem(invItem)); - } - } - - contents.descendents = descendents; - contents.version = inv.Version; - - return reply; - } - /// - /// Old style. Soon to be deprecated. - /// - /// - /// - /// - /// - [Obsolete] - private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) - { - //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count); - - string response = ""; - string bad_folders_response = ""; - - for (int i = 0; i < foldersrequested.Count; i++) - { - string inventoryitemstr = ""; - Hashtable inventoryhash = (Hashtable)foldersrequested[i]; - - LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); - - try - { - LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); - } - catch (Exception e) - { - m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e); - } - - LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); - - if (null == reply) - { - bad_folders_response += "" + llsdRequest.folder_id.ToString() + ""; - } - else - { - inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); - inventoryitemstr = inventoryitemstr.Replace("folders", ""); - inventoryitemstr = inventoryitemstr.Replace("", ""); - } - - response += inventoryitemstr; - } - - if (response.Length == 0) - { - /* Viewers expect a bad_folders array when not available */ - if (bad_folders_response.Length != 0) - { - response = "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders"; - } - } - else - { - if (bad_folders_response.Length != 0) - { - response = "folders" + response + "bad_folders" + bad_folders_response + ""; - } - else - { - response = "folders" + response + ""; - } - } - - // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request"); - //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response); - - return response; - - // } - } - - /// - /// Handle the caps inventory descendents fetch. - /// - /// - /// - /// - /// - /// - /// - /// - /// An empty InventoryCollection if the inventory look up failed - [Obsolete] - private InventoryCollection Fetch( - UUID agentID, UUID folderID, UUID ownerID, - bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents) - { - //m_log.DebugFormat( - // "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}", - // fetchFolders, fetchItems, folderID, agentID); - - // FIXME MAYBE: We're not handling sortOrder! - - version = 0; - descendents = 0; - - InventoryFolderImpl fold; - if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner) - { - if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null) - { - InventoryCollection ret = new InventoryCollection(); - ret.Folders = new List(); - ret.Items = fold.RequestListOfItems(); - descendents = ret.Folders.Count + ret.Items.Count; - - return ret; - } - } - - InventoryCollection contents = new InventoryCollection(); - - if (folderID != UUID.Zero) - { - InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID); - - if (fetchedContents == null) - { - m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID); - return contents; - } - contents = fetchedContents; - InventoryFolderBase containingFolder = new InventoryFolderBase(); - containingFolder.ID = folderID; - containingFolder.Owner = agentID; - containingFolder = m_InventoryService.GetFolder(containingFolder); - - if (containingFolder != null) - { - //m_log.DebugFormat( - // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}", - // containingFolder.Name, containingFolder.ID, agentID); - - version = containingFolder.Version; - - if (fetchItems) - { - List itemsToReturn = contents.Items; - List originalItems = new List(itemsToReturn); - - // descendents must only include the links, not the linked items we add - descendents = originalItems.Count; - - // Add target items for links in this folder before the links themselves. - foreach (InventoryItemBase item in originalItems) - { - if (item.AssetType == (int)AssetType.Link) - { - InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); - - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) - itemsToReturn.Insert(0, linkedItem); - } - } - - // Now scan for folder links and insert the items they target and those links at the head of the return data - foreach (InventoryItemBase item in originalItems) - { - if (item.AssetType == (int)AssetType.LinkFolder) - { - InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID); - List links = linkedFolderContents.Items; - - itemsToReturn.InsertRange(0, links); - - foreach (InventoryItemBase link in linkedFolderContents.Items) - { - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (link != null) - { -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}", -// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name); - - InventoryItemBase linkedItem - = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID)); - - if (linkedItem != null) - itemsToReturn.Insert(0, linkedItem); - } - } - } - } - } - -// foreach (InventoryItemBase item in contents.Items) -// { -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}", -// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID); -// } - - // ===== - -// -// foreach (InventoryItemBase linkedItem in linkedItemsToAdd) -// { -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}", -// linkedItem.Name, folderID, agentID); -// -// contents.Items.Add(linkedItem); -// } -// -// // If the folder requested contains links, then we need to send those folders first, otherwise the links -// // will be broken in the viewer. -// HashSet linkedItemFolderIdsToSend = new HashSet(); -// foreach (InventoryItemBase item in contents.Items) -// { -// if (item.AssetType == (int)AssetType.Link) -// { -// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID)); -// -// // Take care of genuinely broken links where the target doesn't exist -// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, -// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles -// // rather than having to keep track of every folder requested in the recursion. -// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) -// { -// // We don't need to send the folder if source and destination of the link are in the same -// // folder. -// if (linkedItem.Folder != containingFolder.ID) -// linkedItemFolderIdsToSend.Add(linkedItem.Folder); -// } -// } -// } -// -// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend) -// { -// m_log.DebugFormat( -// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}", -// linkedItemFolderId, folderID, agentID); -// -// int dummyVersion; -// InventoryCollection linkedCollection -// = Fetch( -// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion); -// -// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId); -// linkedFolder.Owner = agentID; -// linkedFolder = m_InventoryService.GetFolder(linkedFolder); -// -//// contents.Folders.AddRange(linkedCollection.Folders); -// -// contents.Folders.Add(linkedFolder); -// contents.Items.AddRange(linkedCollection.Items); -// } -// } - } - } - else - { - // Lost items don't really need a version - version = 1; - } - - return contents; - - } - - private void AddLibraryFolders(List fetchFolders, List result) - { - InventoryFolderImpl fold; - if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) - { - List libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner); - fetchFolders.RemoveAll(f => libfolders.Contains(f)); - - //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count); - - foreach (LLSDFetchInventoryDescendents f in libfolders) - { - if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null) - { - InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents(); - ret.Collection = new InventoryCollection(); - ret.Collection.Folders = new List(); - ret.Collection.Items = fold.RequestListOfItems(); - ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner; - ret.Collection.FolderID = f.folder_id; - ret.Collection.Version = fold.Version; - - ret.Descendents = ret.Collection.Items.Count; - result.Add(ret); - - //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID); - } - } - } - } - - private List Fetch(List fetchFolders, List bad_folders) - { - //m_log.DebugFormat( - // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id); - - // FIXME MAYBE: We're not handling sortOrder! - - List result = new List(); - - AddLibraryFolders(fetchFolders, result); - - if (fetchFolders.Count > 0) - { - UUID[] fids = new UUID[fetchFolders.Count]; - int i = 0; - foreach (LLSDFetchInventoryDescendents f in fetchFolders) - fids[i++] = f.folder_id; - - //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids)); - - InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids); - - if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0)) - { - //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id); - return null; - } - - i = 0; - // Do some post-processing. May need to fetch more from inv server for links - foreach (InventoryCollection contents in fetchedContents) - { - // Find the original request - LLSDFetchInventoryDescendents freq = fetchFolders[i++]; - - InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents(); - coll.Collection = contents; - - if (BadFolder(freq, contents, bad_folders)) - continue; - - // Next: link management - ProcessLinks(freq, coll); - - result.Add(coll); - } - } - - return result; - } - - private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List bad_folders) - { - bool bad = false; - if (contents == null) - { - bad_folders.Add(freq.folder_id); - bad = true; - } - - // The inventory server isn't sending FolderID in the collection... - // Must fetch it individually - if (contents.FolderID == UUID.Zero) - { - InventoryFolderBase containingFolder = new InventoryFolderBase(); - containingFolder.ID = freq.folder_id; - containingFolder.Owner = freq.owner_id; - containingFolder = m_InventoryService.GetFolder(containingFolder); - - if (containingFolder != null) - { - contents.FolderID = containingFolder.ID; - contents.OwnerID = containingFolder.Owner; - contents.Version = containingFolder.Version; - } - else - { - // Was it really a request for folder Zero? - // This is an overkill, but Firestorm really asks for folder Zero. - // I'm leaving the code here for the time being, but commented. - if (freq.folder_id == UUID.Zero) - { - //coll.Collection.OwnerID = freq.owner_id; - //coll.Collection.FolderID = contents.FolderID; - //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id); - //if (containingFolder != null) - //{ - // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID); - // coll.Collection.Folders.Clear(); - // coll.Collection.Folders.Add(containingFolder); - // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null) - // { - // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner); - // lib.Name = m_LibraryService.LibraryRootFolder.Name; - // lib.Type = m_LibraryService.LibraryRootFolder.Type; - // lib.Version = m_LibraryService.LibraryRootFolder.Version; - // coll.Collection.Folders.Add(lib); - // } - // coll.Collection.Items.Clear(); - //} - } - else - { - m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id); - bad_folders.Add(freq.folder_id); - } - bad = true; - } - } - - return bad; - } - - private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll) - { - InventoryCollection contents = coll.Collection; - - if (freq.fetch_items && contents.Items != null) - { - List itemsToReturn = contents.Items; - - // descendents must only include the links, not the linked items we add - coll.Descendents = itemsToReturn.Count; - - // Add target items for links in this folder before the links themselves. - List itemIDs = new List(); - List folderIDs = new List(); - foreach (InventoryItemBase item in itemsToReturn) - { - //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType); - if (item.AssetType == (int)AssetType.Link) - itemIDs.Add(item.AssetID); - - else if (item.AssetType == (int)AssetType.LinkFolder) - folderIDs.Add(item.AssetID); - } - - //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); - - // Scan for folder links and insert the items they target and those links at the head of the return data - if (folderIDs.Count > 0) - { - InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray()); - foreach (InventoryCollection linkedFolderContents in linkedFolders) - { - List links = linkedFolderContents.Items; - - itemsToReturn.InsertRange(0, links); - - foreach (InventoryItemBase link in linkedFolderContents.Items) - { - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (link != null) - { - //m_log.DebugFormat( - // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", - // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID); - itemIDs.Add(link.ID); - } - } - } - } - - if (itemIDs.Count > 0) - { - InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray()); - if (linked == null) - { - // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated - m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one."); - linked = new InventoryItemBase[itemIDs.Count]; - int i = 0; - InventoryItemBase item = new InventoryItemBase(); - item.Owner = freq.owner_id; - foreach (UUID id in itemIDs) - { - item.ID = id; - linked[i++] = m_InventoryService.GetItem(item); - } - } - - //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id); - //foreach (InventoryItemBase item in itemsToReturn) - // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder); - - if (linked != null) - { - foreach (InventoryItemBase linkedItem in linked) - { - // Take care of genuinely broken links where the target doesn't exist - // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // rather than having to keep track of every folder requested in the recursion. - if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link) - { - itemsToReturn.Insert(0, linkedItem); - //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder); - } - } - } - } - } - - } - - /// - /// Convert an internal inventory folder object into an LLSD object. - /// - /// - /// - private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder) - { - LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder(); - llsdFolder.folder_id = invFolder.ID; - llsdFolder.parent_id = invFolder.ParentID; - llsdFolder.name = invFolder.Name; - llsdFolder.type = invFolder.Type; - llsdFolder.preferred_type = -1; - - return llsdFolder; - } - - /// - /// Convert an internal inventory item object into an LLSD object. - /// - /// - /// - private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) - { - LLSDInventoryItem llsdItem = new LLSDInventoryItem(); - llsdItem.asset_id = invItem.AssetID; - llsdItem.created_at = invItem.CreationDate; - llsdItem.desc = invItem.Description; - llsdItem.flags = (int)invItem.Flags; - llsdItem.item_id = invItem.ID; - llsdItem.name = invItem.Name; - llsdItem.parent_id = invItem.Folder; - llsdItem.type = invItem.AssetType; - llsdItem.inv_type = invItem.InvType; - - llsdItem.permissions = new LLSDPermissions(); - llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; - llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; - llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; - llsdItem.permissions.group_id = invItem.GroupID; - llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; - llsdItem.permissions.is_owner_group = invItem.GroupOwned; - llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; - llsdItem.permissions.owner_id = invItem.Owner; - llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; - llsdItem.sale_info = new LLSDSaleInfo(); - llsdItem.sale_info.sale_price = invItem.SalePrice; - llsdItem.sale_info.sale_type = invItem.SaleType; - - return llsdItem; - } - } - - class InventoryCollectionWithDescendents - { - public InventoryCollection Collection; - public int Descendents; - } -} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs deleted file mode 100644 index 6fbe173..0000000 --- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 Nini.Config; -using OpenSim.Server.Base; -using OpenSim.Services.Interfaces; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Server.Handlers.Base; -using OpenMetaverse; - -namespace OpenSim.Capabilities.Handlers -{ - public class FetchInvDescServerConnector : ServiceConnector - { - private IInventoryService m_InventoryService; - private ILibraryService m_LibraryService; - private string m_ConfigName = "CapsService"; - - public FetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) : - base(config, server, configName) - { - if (configName != String.Empty) - m_ConfigName = configName; - - IConfig serverConfig = config.Configs[m_ConfigName]; - if (serverConfig == null) - throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); - - string invService = serverConfig.GetString("InventoryService", String.Empty); - - if (invService == String.Empty) - throw new Exception("No InventoryService in config file"); - - Object[] args = new Object[] { config }; - m_InventoryService = - ServerUtils.LoadPlugin(invService, args); - - if (m_InventoryService == null) - throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); - - string libService = serverConfig.GetString("LibraryService", String.Empty); - m_LibraryService = - ServerUtils.LoadPlugin(libService, args); - - FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService); - IRequestHandler reqHandler - = new RestStreamHandler( - "POST", - "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, - webFetchHandler.FetchInventoryDescendentsRequest, - "FetchInvDescendents", - null); - server.AddStreamHandler(reqHandler); - } - - } -} -- cgit v1.1 From 05737a10109532fbaa01bdba0978a1035d25e18c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 08:59:33 -0700 Subject: Improved comments on fetch inventory tests --- .../Tests/FetchInventoryDescendents2HandlerTests.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs index 1064c7b..d34423d 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs @@ -54,7 +54,18 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests private void Init() { - // CreateInventoryFolder an inventory + // Create an inventory that looks like this: + // + // /My Inventory + // + // /Objects + // Some Object + // /Notecards + // Notecard 1 + // Notecard 2 + // /Test Folder + // Link to notecard -> /Notecards/Notecard 2 + // Link to Objects folder -> /Objects m_scene = new SceneHelpers().SetupScene(); -- cgit v1.1 From c2cf22ea4fc42d8582aa6aa2df48a3ce06813d56 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 21:04:46 -0700 Subject: Added the beginning of a new test framework for robust connectors and services. For now, just Grid and Presence. This framework starts a robust server (as a thread) listening on a port in localhost, then the tests are client code. --- OpenSim/Server/Base/ServicesServerBase.cs | 10 +- OpenSim/Tests/Robust/Clients/Grid/GridClient.cs | 133 +++++++++++++++++++++ .../Robust/Clients/Presence/PresenceClient.cs | 81 +++++++++++++ OpenSim/Tests/Robust/Server/DemonServer.cs | 67 +++++++++++ 4 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 OpenSim/Tests/Robust/Clients/Grid/GridClient.cs create mode 100644 OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs create mode 100644 OpenSim/Tests/Robust/Server/DemonServer.cs (limited to 'OpenSim') diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index d7d1306..1f2c54d 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -82,7 +82,9 @@ namespace OpenSim.Server.Base argvConfig.AddSwitch("Startup", "logconfig", "g"); // Automagically create the ini file name - string fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); + string fileName = ""; + if (Assembly.GetEntryAssembly() != null) + fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); string iniFile = fileName + ".ini"; string logConfig = null; @@ -158,7 +160,11 @@ namespace OpenSim.Server.Base MainConsole.Instance = new RemoteConsole(prompt); ((RemoteConsole)MainConsole.Instance).ReadConfig(Config); } - else + else if (consoleType == "mock") + { + MainConsole.Instance = new MockConsole(); + } + else if (consoleType == "local") { MainConsole.Instance = new LocalConsole(prompt, startupConfig); } diff --git a/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs b/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs new file mode 100644 index 0000000..671aca7 --- /dev/null +++ b/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs @@ -0,0 +1,133 @@ +/* + * 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 System.Collections.Generic; +using System.Text; +using System.Reflection; + +using OpenMetaverse; +using NUnit.Framework; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Services.Connectors; + +namespace Robust.Tests +{ + [TestFixture] + public class GridClient + { +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + [Test] + public void Grid_001() + { + GridServicesConnector m_Connector = new GridServicesConnector(DemonServer.Address); + + GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000); + GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000); + GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000); + + string msg = m_Connector.RegisterRegion(UUID.Zero, r1); + Assert.AreEqual(msg, string.Empty, "Region 1 failed to register"); + + msg = m_Connector.RegisterRegion(UUID.Zero, r2); + Assert.AreEqual(msg, string.Empty, "Region 2 failed to register"); + + msg = m_Connector.RegisterRegion(UUID.Zero, r3); + Assert.AreEqual(msg, string.Empty, "Region 3 failed to register"); + + bool success; + success = m_Connector.DeregisterRegion(r3.RegionID); + Assert.AreEqual(success, true, "Region 3 failed to deregister"); + + msg = m_Connector.RegisterRegion(UUID.Zero, r3); + Assert.AreEqual(msg, string.Empty, "Region 3 failed to re-register"); + + List regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID); + Assert.AreNotEqual(regions, null, "GetNeighbours of region 1 failed"); + Assert.AreEqual(regions.Count, 1, "Region 1 should have 1 neighbor"); + Assert.AreEqual(regions[0].RegionName, "Test Region 2", "Region 1 has the wrong neighbor"); + + GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID); + Assert.AreNotEqual(region, null, "GetRegionByUUID for region 2 failed"); + Assert.AreEqual(region.RegionName, "Test Region 2", "GetRegionByUUID of region 2 returned wrong region"); + + region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random()); + Assert.AreEqual(region, null, "Region with randon id should not exist"); + + region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName); + Assert.AreNotEqual(region, null, "GetRegionByUUID for region 3 failed"); + Assert.AreEqual(region.RegionName, "Test Region 3", "GetRegionByUUID of region 3 returned wrong region"); + + region = m_Connector.GetRegionByName(UUID.Zero, "Foo"); + Assert.AreEqual(region, null, "Region Foo should not exist"); + + regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10); + Assert.AreNotEqual(regions, null, "GetRegionsByName failed"); + Assert.AreEqual(regions.Count, 3, "GetRegionsByName should return 3"); + + regions = m_Connector.GetRegionRange(UUID.Zero, + (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002), + (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) ); + Assert.AreNotEqual(regions, null, "GetRegionRange failed"); + Assert.AreEqual(regions.Count, 2, "GetRegionRange should return 2"); + + regions = m_Connector.GetRegionRange(UUID.Zero, + (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950), + (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) ); + Assert.AreNotEqual(regions, null, "GetRegionRange (bis) failed"); + Assert.AreEqual(regions.Count, 0, "GetRegionRange (bis) should return 0"); + + // Deregister them all + success = m_Connector.DeregisterRegion(r1.RegionID); + Assert.AreEqual(success, true, "Region 1 failed to deregister"); + + success = m_Connector.DeregisterRegion(r2.RegionID); + Assert.AreEqual(success, true, "Region 2 failed to deregister"); + + success = m_Connector.DeregisterRegion(r3.RegionID); + Assert.AreEqual(success, true, "Region 3 failed to deregister"); + } + + private static GridRegion CreateRegion(string name, uint xcell, uint ycell) + { + GridRegion region = new GridRegion(xcell, ycell); + region.RegionName = name; + region.RegionID = UUID.Random(); + region.ExternalHostName = "127.0.0.1"; + region.HttpPort = 9000; + region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000); + + return region; + } + } +} diff --git a/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs b/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs new file mode 100644 index 0000000..31c8ee9 --- /dev/null +++ b/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs @@ -0,0 +1,81 @@ +/* + * 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 System.Collections.Generic; +using System.Text; +using System.Reflection; + +using OpenMetaverse; +using NUnit.Framework; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors; + +namespace Robust.Tests +{ + [TestFixture] + public class PresenceClient + { + [Test] + public void Presence_001() + { + PresenceServicesConnector m_Connector = new PresenceServicesConnector(DemonServer.Address); + + UUID user1 = UUID.Random(); + UUID session1 = UUID.Random(); + UUID region1 = UUID.Random(); + + bool success = m_Connector.LoginAgent(user1.ToString(), session1, UUID.Zero); + Assert.AreEqual(success, true, "Failed to add user session"); + + PresenceInfo pinfo = m_Connector.GetAgent(session1); + Assert.AreNotEqual(pinfo, null, "Unable to retrieve session"); + Assert.AreEqual(pinfo.UserID, user1.ToString(), "Retrieved session does not match expected userID"); + Assert.AreNotEqual(pinfo.RegionID, region1, "Retrieved session is unexpectedly in region"); + + success = m_Connector.ReportAgent(session1, region1); + Assert.AreEqual(success, true, "Failed to report session in region 1"); + + pinfo = m_Connector.GetAgent(session1); + Assert.AreNotEqual(pinfo, null, "Unable to session presence"); + Assert.AreEqual(pinfo.UserID, user1.ToString(), "Retrieved session does not match expected userID"); + Assert.AreEqual(pinfo.RegionID, region1, "Retrieved session is not in expected region"); + + success = m_Connector.LogoutAgent(session1); + Assert.AreEqual(success, true, "Failed to remove session"); + + pinfo = m_Connector.GetAgent(session1); + Assert.AreEqual(pinfo, null, "Session is still there, even though it shouldn't"); + + success = m_Connector.ReportAgent(session1, UUID.Random()); + Assert.AreEqual(success, false, "Remove non-existing session should fail"); + } + + } +} diff --git a/OpenSim/Tests/Robust/Server/DemonServer.cs b/OpenSim/Tests/Robust/Server/DemonServer.cs new file mode 100644 index 0000000..b51a6bb --- /dev/null +++ b/OpenSim/Tests/Robust/Server/DemonServer.cs @@ -0,0 +1,67 @@ +/* + * 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 System.Collections.Generic; +using System.IO; +using System.Threading; + +using Nini.Config; +using log4net; +using NUnit.Framework; + +using OpenSim.Server; + +namespace Robust.Tests +{ + [SetUpFixture] + public class DemonServer : OpenSimServer + { + private Thread m_demon; + + public static string Address = "http://localhost:8888"; + + [SetUp] + public void StartDemon() + { + if (File.Exists("Robust.Tests.log")) + File.Delete("Robust.Tests.log"); + + Console.WriteLine("**** Starting demon Robust server ****"); + m_demon = new Thread( () => Main(new string[] {"-inifile=Robust.Tests.ini"})); + m_demon.Start(); + Console.WriteLine("**** Setup Finished ****"); + } + + [TearDown] + public void StopDemon() + { + Console.WriteLine("**** Killing demon Robust Server ****"); + m_Server.Shutdown(); + } + } +} -- cgit v1.1 From 811b026ed58f432c3b77d1f710c102f355853c9a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 21:15:22 -0700 Subject: Deleted OpenSim.Tests.Client.GridClient and PresenceClient, as they have been subsumed by the new testing framework. --- OpenSim/Tests/Clients/Grid/GridClient.cs | 205 ---------------------- OpenSim/Tests/Clients/Grid/GridForm.html | 11 -- OpenSim/Tests/Clients/Presence/OpenSim.Server.ini | 33 ---- OpenSim/Tests/Clients/Presence/PresenceClient.cs | 115 ------------ 4 files changed, 364 deletions(-) delete mode 100644 OpenSim/Tests/Clients/Grid/GridClient.cs delete mode 100644 OpenSim/Tests/Clients/Grid/GridForm.html delete mode 100644 OpenSim/Tests/Clients/Presence/OpenSim.Server.ini delete mode 100644 OpenSim/Tests/Clients/Presence/PresenceClient.cs (limited to 'OpenSim') diff --git a/OpenSim/Tests/Clients/Grid/GridClient.cs b/OpenSim/Tests/Clients/Grid/GridClient.cs deleted file mode 100644 index fed7a16..0000000 --- a/OpenSim/Tests/Clients/Grid/GridClient.cs +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using log4net; -using log4net.Appender; -using log4net.Layout; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Services.Connectors; - -namespace OpenSim.Tests.Clients.GridClient -{ - public class GridClient - { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - - public static void Main(string[] args) - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - - string serverURI = "http://127.0.0.1:8001"; - GridServicesConnector m_Connector = new GridServicesConnector(serverURI); - - GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000); - GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000); - GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000); - - Console.WriteLine("[GRID CLIENT]: *** Registering region 1"); - string msg = m_Connector.RegisterRegion(UUID.Zero, r1); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 1"); - else - Console.WriteLine("[GRID CLIENT]: region 1 failed to register"); - - Console.WriteLine("[GRID CLIENT]: *** Registering region 2"); - msg = m_Connector.RegisterRegion(UUID.Zero, r2); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 2"); - else - Console.WriteLine("[GRID CLIENT]: region 2 failed to register"); - - Console.WriteLine("[GRID CLIENT]: *** Registering region 3"); - msg = m_Connector.RegisterRegion(UUID.Zero, r3); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to register"); - - - bool success; - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3"); - success = m_Connector.DeregisterRegion(r3.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister"); - Console.WriteLine("[GRID CLIENT]: *** Registering region 3 again"); - msg = m_Connector.RegisterRegion(UUID.Zero, r3); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to register"); - - Console.WriteLine("[GRID CLIENT]: *** GetNeighbours of region 1"); - List regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 failed"); - else if (regions.Count > 0) - { - if (regions.Count != 1) - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned more neighbours than expected: " + regions.Count); - else - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned the right neighbour " + regions[0].RegionName); - } - else - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned 0 neighbours"); - - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of region 2 (this should succeed)"); - GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of non-existent region (this should fail)"); - region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random()); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of region 3 (this should succeed)"); - region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of non-existent region (this should fail)"); - region = m_Connector.GetRegionByName(UUID.Zero, "Foo"); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionsByName (this should return 3 regions)"); - regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned " + regions.Count + " regions"); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 2 regions)"); - regions = m_Connector.GetRegionRange(UUID.Zero, - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002), - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) ); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions"); - Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 0 regions)"); - regions = m_Connector.GetRegionRange(UUID.Zero, - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950), - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) ); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions"); - - Console.Write("Proceed to deregister? Press enter..."); - Console.ReadLine(); - - // Deregister them all - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 1"); - success = m_Connector.DeregisterRegion(r1.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 1"); - else - Console.WriteLine("[GRID CLIENT]: region 1 failed to deregister"); - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 2"); - success = m_Connector.DeregisterRegion(r2.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 2"); - else - Console.WriteLine("[GRID CLIENT]: region 2 failed to deregister"); - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3"); - success = m_Connector.DeregisterRegion(r3.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister"); - - } - - private static GridRegion CreateRegion(string name, uint xcell, uint ycell) - { - GridRegion region = new GridRegion(xcell, ycell); - region.RegionName = name; - region.RegionID = UUID.Random(); - region.ExternalHostName = "127.0.0.1"; - region.HttpPort = 9000; - region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000); - - return region; - } - } -} diff --git a/OpenSim/Tests/Clients/Grid/GridForm.html b/OpenSim/Tests/Clients/Grid/GridForm.html deleted file mode 100644 index 252920f..0000000 --- a/OpenSim/Tests/Clients/Grid/GridForm.html +++ /dev/null @@ -1,11 +0,0 @@ - - -
-xmin: -xmax: -ymin: -ymax: - - -
- diff --git a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini deleted file mode 100644 index 8610c78..0000000 --- a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini +++ /dev/null @@ -1,33 +0,0 @@ -; * Run a ROBUST server shell like this, from bin: -; * $ OpenSim.Server.exe -inifile ../OpenSim/Tests/Clients/Presence/OpenSim.Server.ini -; * -; * Then run this client like this, from bin: -; * $ OpenSim.Tests.Clients.PresenceClient.exe -; * -; * - -[Startup] -ServiceConnectors = "OpenSim.Server.Handlers.dll:PresenceServiceConnector" - -; * This is common for all services, it's the network setup for the entire -; * server instance -; * -[Network] -port = 8003 - -; * The following are for the remote console -; * They have no effect for the local or basic console types -; * Leave commented to diable logins to the console -;ConsoleUser = Test -;ConsolePass = secret - -; * As an example, the below configuration precisely mimicks the legacy -; * asset server. It is read by the asset IN connector (defined above) -; * and it then loads the OUT connector (a local database module). That, -; * in turn, reads the asset loader and database connection information -; * -[PresenceService] - LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" - StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" - diff --git a/OpenSim/Tests/Clients/Presence/PresenceClient.cs b/OpenSim/Tests/Clients/Presence/PresenceClient.cs deleted file mode 100644 index fd3905a..0000000 --- a/OpenSim/Tests/Clients/Presence/PresenceClient.cs +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using log4net; -using log4net.Appender; -using log4net.Layout; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors; - -namespace OpenSim.Tests.Clients.PresenceClient -{ - public class PresenceClient - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - public static void Main(string[] args) - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - - string serverURI = "http://127.0.0.1:8003"; - PresenceServicesConnector m_Connector = new PresenceServicesConnector(serverURI); - - UUID user1 = UUID.Random(); - UUID session1 = UUID.Random(); - UUID region1 = UUID.Random(); - - bool success = m_Connector.LoginAgent(user1.ToString(), session1, UUID.Zero); - if (success) - m_log.InfoFormat("[PRESENCE CLIENT]: Successfully logged in user {0} with session {1}", user1, session1); - else - m_log.InfoFormat("[PRESENCE CLIENT]: failed to login user {0}", user1); - - System.Console.WriteLine("\n"); - - PresenceInfo pinfo = m_Connector.GetAgent(session1); - if (pinfo == null) - m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0}", user1); - else - m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; regionID={1}", - pinfo.UserID, pinfo.RegionID); - - System.Console.WriteLine("\n"); - success = m_Connector.ReportAgent(session1, region1); - if (success) - m_log.InfoFormat("[PRESENCE CLIENT]: Successfully reported session {0} in region {1}", user1, region1); - else - m_log.InfoFormat("[PRESENCE CLIENT]: failed to report session {0}", session1); - pinfo = m_Connector.GetAgent(session1); - if (pinfo == null) - m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0} for second time", user1); - else - m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; regionID={2}", - pinfo.UserID, pinfo.RegionID); - - System.Console.WriteLine("\n"); - success = m_Connector.LogoutAgent(session1); - if (success) - m_log.InfoFormat("[PRESENCE CLIENT]: Successfully logged out user {0}", user1); - else - m_log.InfoFormat("[PRESENCE CLIENT]: failed to logout user {0}", user1); - pinfo = m_Connector.GetAgent(session1); - if (pinfo == null) - m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0} for fourth time", user1); - else - m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; regionID={1}", - pinfo.UserID, pinfo.RegionID); - - System.Console.WriteLine("\n"); - success = m_Connector.ReportAgent(session1, UUID.Random()); - if (success) - m_log.InfoFormat("[PRESENCE CLIENT]: Report agent succeeded, but this is wrong"); - else - m_log.InfoFormat("[PRESENCE CLIENT]: failed to report agent, as it should because user is not logged in"); - - } - - } -} -- cgit v1.1 From 4b94fb8443ff2e6f0aa7b176ca81e5021d6f59b6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 21:16:12 -0700 Subject: Added this form that comes handy for testing the grid service in Robust. --- OpenSim/Tests/Robust/Clients/Grid/GridForm.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 OpenSim/Tests/Robust/Clients/Grid/GridForm.html (limited to 'OpenSim') diff --git a/OpenSim/Tests/Robust/Clients/Grid/GridForm.html b/OpenSim/Tests/Robust/Clients/Grid/GridForm.html new file mode 100644 index 0000000..252920f --- /dev/null +++ b/OpenSim/Tests/Robust/Clients/Grid/GridForm.html @@ -0,0 +1,11 @@ + + +
+xmin: +xmax: +ymin: +ymax: + + +
+ -- cgit v1.1 From eb9b16d2849de438f20bb269ef3ea93e33f4d18d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 21:49:24 -0700 Subject: Added simple test for IM in Robust too. Changed Inventory data to use the mock one in Common Tests. (but still not inventory tests) --- .../HypergridService/HGInstantMessageService.cs | 9 ++- OpenSim/Tests/Clients/InstantMessage/IMClient.cs | 75 ---------------------- .../Robust/Clients/InstantMessage/IMClient.cs | 58 +++++++++++++++++ 3 files changed, 66 insertions(+), 76 deletions(-) delete mode 100644 OpenSim/Tests/Clients/InstantMessage/IMClient.cs create mode 100644 OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs (limited to 'OpenSim') diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 9b7b278..dde0e6c 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -101,7 +101,14 @@ namespace OpenSim.Services.HypergridService Object[] args = new Object[] { config }; m_GridService = ServerUtils.LoadPlugin(gridService, args); m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); - m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + try + { + m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + } + catch (Exception e) + { + m_log.WarnFormat("[HG IM SERVICE]: Unable to create User Agent Service. Missing config var in [HGInstantMessageService]?"); + } m_RegionCache = new ExpiringCache(); diff --git a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs deleted file mode 100644 index e7304a2..0000000 --- a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using log4net; -using log4net.Appender; -using log4net.Layout; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors.InstantMessage; - -namespace OpenSim.Tests.Clients.InstantMessage -{ - public class IMClient - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - public static void Main(string[] args) - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - - string serverURI = "http://127.0.0.1:8002"; - GridInstantMessage im = new GridInstantMessage(); - im.fromAgentID = new Guid(); - im.toAgentID = new Guid(); - im.message = "Hello"; - im.imSessionID = new Guid(); - - bool success = InstantMessageServiceConnector.SendInstantMessage(serverURI, im); - - if (success) - m_log.InfoFormat("[IM CLIENT]: Successfully IMed {0}", serverURI); - else - m_log.InfoFormat("[IM CLIENT]: failed to IM {0}", serverURI); - - System.Console.WriteLine("\n"); - } - - } -} diff --git a/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs new file mode 100644 index 0000000..8f312eb --- /dev/null +++ b/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs @@ -0,0 +1,58 @@ +/* + * 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 System.Collections.Generic; +using System.Text; + +using OpenMetaverse; +using NUnit.Framework; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; + +namespace Robust.Tests +{ + [TestFixture] + public class IMClient + { + [Test] + public void HGIM_001() + { + GridInstantMessage im = new GridInstantMessage(); + im.fromAgentID = new Guid(); + im.toAgentID = new Guid(); + im.message = "Hello"; + im.imSessionID = new Guid(); + + bool success = InstantMessageServiceConnector.SendInstantMessage(DemonServer.Address, im); + Assert.IsFalse(success, "Sending of IM succeeded, but it should have failed"); + } + + } +} -- cgit v1.1 From 3c596e47c6322ef608233fb45624c2f26fa6b5f0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 10 May 2015 21:54:24 -0700 Subject: Knocked off a few compiler warnings regarding unused variables. --- OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs | 1 - OpenSim/Services/HypergridService/HGInstantMessageService.cs | 2 +- 8 files changed, 1 insertion(+), 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs index 0df7132..32f1de9 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs @@ -40,7 +40,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs index 3e4a457..2ab4bcc 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs @@ -38,7 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs index 02f1852..0939c0a 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs @@ -38,7 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs index 2db49c8..cbbccc0 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs @@ -38,7 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs index 53a64df..d6b95d0 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs @@ -39,7 +39,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs index 9ac1edd..35fb9d6 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs @@ -38,7 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs index 72b172c..9f8d5b2 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs @@ -38,7 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers public override string ModifyTerrain(ITerrainChannel map, string[] args) { - string val; string result; if (args.Length < 3) { diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index dde0e6c..32ca09a 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -105,7 +105,7 @@ namespace OpenSim.Services.HypergridService { m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); } - catch (Exception e) + catch { m_log.WarnFormat("[HG IM SERVICE]: Unable to create User Agent Service. Missing config var in [HGInstantMessageService]?"); } -- cgit v1.1 From 3df472f10d1a2b8387e998c4f4c871eaf9a73ac2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 11 May 2015 08:52:12 -0700 Subject: Added inventory tests to Robust.Tests. --- .../Inventory/XInventoryServicesConnector.cs | 6 +- .../Services/InventoryService/XInventoryService.cs | 12 +- .../Robust/Clients/Inventory/InventoryClient.cs | 152 +++++++++++++++++++++ OpenSim/Tests/Robust/Server/DemonServer.cs | 2 + 4 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 0cea4a1..db3c857 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -406,9 +406,13 @@ namespace OpenSim.Services.Connectors public bool AddItem(InventoryItemBase item) { + if (item.Description == null) + item.Description = String.Empty; if (item.CreatorData == null) item.CreatorData = String.Empty; - Dictionary ret = MakeRequest("ADDITEM", + if (item.CreatorId == null) + item.CreatorId = String.Empty; + Dictionary ret = MakeRequest("ADDITEM", new Dictionary { { "AssetID", item.AssetID.ToString() }, { "AssetType", item.AssetType.ToString() }, diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 50cadab..64f727c 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -261,7 +261,7 @@ namespace OpenSim.Services.InventoryService private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type) { -// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); + //m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0}", type); if (type == AssetType.RootFolder) return rootFolder; @@ -272,13 +272,13 @@ namespace OpenSim.Services.InventoryService if (folders.Length == 0) { -// m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID); + //m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} ", type); return null; } - -// m_log.DebugFormat( -// "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}", -// folders[0].folderName, folders[0].folderID, type, principalID); + + //m_log.DebugFormat( + // "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2}", + // folders[0].folderName, folders[0].folderID, type); return ConvertToOpenSim(folders[0]); } diff --git a/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs new file mode 100644 index 0000000..78a7dc8 --- /dev/null +++ b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs @@ -0,0 +1,152 @@ +/* + * 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 System.Collections.Generic; +using System.Text; +using System.Reflection; + +using OpenMetaverse; +using NUnit.Framework; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors; + +namespace Robust.Tests +{ + [TestFixture] + public class InventoryClient + { +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + private UUID m_userID = new UUID("00000000-0000-0000-0000-333333333333"); + private UUID m_rootFolderID; + private UUID m_notecardsFolder; + private UUID m_objectsFolder; + + [Test] + public void Inventory_001_CreateInventory() + { + XInventoryServicesConnector m_Connector = new XInventoryServicesConnector(DemonServer.Address); + + // Create an inventory that looks like this: + // + // /My Inventory + // + // /Objects + // Some Object + // /Notecards + // Notecard 1 + // Notecard 2 + // /Test Folder + // Link to notecard -> /Notecards/Notecard 2 + // Link to Objects folder -> /Objects + + Console.WriteLine("Starting inventory test"); + bool success = m_Connector.CreateUserInventory(m_userID); + Assert.IsTrue(success, "Failed to create user inventory"); + + m_rootFolderID = m_Connector.GetRootFolder(m_userID).ID; + Assert.AreNotEqual(m_rootFolderID, UUID.Zero, "Root folder ID must not be UUID.Zero"); + + InventoryFolderBase of = m_Connector.GetFolderForType(m_userID, AssetType.Object); + Assert.IsNotNull(of, "Failed to retrieve Objects folder"); + m_objectsFolder = of.ID; + Assert.AreNotEqual(m_objectsFolder, UUID.Zero, "Objects folder ID must not be UUID.Zero"); + + // Add an object + InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID); + item.AssetID = UUID.Random(); + item.AssetType = (int)AssetType.Object; + item.Folder = m_objectsFolder; + item.Name = "Some Object"; + item.Description = string.Empty; + success = m_Connector.AddItem(item); + Assert.IsTrue(success, "Failed to add object to inventory"); + + InventoryFolderBase ncf = m_Connector.GetFolderForType(m_userID, AssetType.Notecard); + Assert.IsNotNull(of, "Failed to retrieve Notecards folder"); + m_notecardsFolder = ncf.ID; + Assert.AreNotEqual(m_notecardsFolder, UUID.Zero, "Notecards folder ID must not be UUID.Zero"); + m_notecardsFolder = ncf.ID; + + // Add a notecard + item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID); + item.AssetID = UUID.Random(); + item.AssetType = (int)AssetType.Notecard; + item.Folder = m_notecardsFolder; + item.Name = "Test Notecard 1"; + item.Description = string.Empty; + success = m_Connector.AddItem(item); + Assert.IsTrue(success, "Failed to add Notecard 1 to inventory"); + // Add another notecard + item.ID = new UUID("20000000-0000-0000-0000-000000000002"); + item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a"); + item.Name = "Test Notecard 2"; + item.Description = string.Empty; + success = m_Connector.AddItem(item); + Assert.IsTrue(success, "Failed to add Notecard 2 to inventory"); + + // Add a folder + InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID); + folder.Type = (int)AssetType.Folder; + success = m_Connector.AddFolder(folder); + Assert.IsTrue(success, "Failed to add Test Folder to inventory"); + + // Add a link to notecard 2 in Test Folder + item.AssetID = item.ID; // use item ID of notecard 2 + item.ID = new UUID("40000000-0000-0000-0000-000000000004"); + item.AssetType = (int)AssetType.Link; + item.Folder = folder.ID; + item.Name = "Link to notecard"; + item.Description = string.Empty; + success = m_Connector.AddItem(item); + Assert.IsTrue(success, "Failed to add link to notecard to inventory"); + + // Add a link to the Objects folder in Test Folder + item.AssetID = m_Connector.GetFolderForType(m_userID, AssetType.Object).ID; // use item ID of Objects folder + item.ID = new UUID("50000000-0000-0000-0000-000000000005"); + item.AssetType = (int)AssetType.LinkFolder; + item.Folder = folder.ID; + item.Name = "Link to Objects folder"; + item.Description = string.Empty; + success = m_Connector.AddItem(item); + Assert.IsTrue(success, "Failed to add link to objects folder to inventory"); + + InventoryCollection coll = m_Connector.GetFolderContent(m_userID, m_rootFolderID); + Assert.IsNotNull(coll, "Failed to retrieve contents of root folder"); + Assert.Greater(coll.Folders.Count, 0, "Root folder does not have any subfolders"); + + coll = m_Connector.GetFolderContent(m_userID, folder.ID); + Assert.IsNotNull(coll, "Failed to retrieve contents of Test Folder"); + Assert.AreEqual(coll.Items.Count + coll.Folders.Count, 2, "Test Folder is expected to have exactly 2 things inside"); + } + } +} diff --git a/OpenSim/Tests/Robust/Server/DemonServer.cs b/OpenSim/Tests/Robust/Server/DemonServer.cs index b51a6bb..1e0797e 100644 --- a/OpenSim/Tests/Robust/Server/DemonServer.cs +++ b/OpenSim/Tests/Robust/Server/DemonServer.cs @@ -54,6 +54,8 @@ namespace Robust.Tests Console.WriteLine("**** Starting demon Robust server ****"); m_demon = new Thread( () => Main(new string[] {"-inifile=Robust.Tests.ini"})); m_demon.Start(); + // Give some time for the server to instantiate all services + Thread.Sleep(3000); Console.WriteLine("**** Setup Finished ****"); } -- cgit v1.1 From c20a5dd75a31c99939046d5fb59769d8fff43531 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 11 May 2015 09:05:09 -0700 Subject: Trivial change just to trigger jenkins to build again --- OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim') diff --git a/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs index 78a7dc8..9d3f400 100644 --- a/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs +++ b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs @@ -147,6 +147,7 @@ namespace Robust.Tests coll = m_Connector.GetFolderContent(m_userID, folder.ID); Assert.IsNotNull(coll, "Failed to retrieve contents of Test Folder"); Assert.AreEqual(coll.Items.Count + coll.Folders.Count, 2, "Test Folder is expected to have exactly 2 things inside"); + } } } -- cgit v1.1 From 923a57a91fa9629a844da6cd59ca8e9d2b0fbcde Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 11 May 2015 19:55:23 -0700 Subject: Added tests for UserAccountService in Robust. In the process fixed a couple of bugs in the network connectors. For some reason the robust-bound code had a CreateUser method, while the client-bound code had no such method. I assume someone is extending the client-side code with their own connectors. I added the missing method, but didn't add it to the service interface. --- .../UserAccounts/UserAccountServerPostHandler.cs | 3 +- .../UserAccounts/UserAccountServicesConnector.cs | 35 ++++- .../Tests/Clients/UserAccounts/OpenSim.Server.ini | 33 ----- .../Clients/UserAccounts/UserAccountsClient.cs | 144 --------------------- .../Clients/UserAccounts/UserAccountsClient.cs | 81 ++++++++++++ 5 files changed, 115 insertions(+), 181 deletions(-) delete mode 100644 OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini delete mode 100644 OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs create mode 100644 OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs (limited to 'OpenSim') diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs index a77d78e..21eb790 100644 --- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs +++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs @@ -257,8 +257,7 @@ namespace OpenSim.Server.Handlers.UserAccounts byte[] CreateUser(Dictionary request) { - if (! - request.ContainsKey("FirstName") + if (! request.ContainsKey("FirstName") && request.ContainsKey("LastName") && request.ContainsKey("Password")) return FailureResult(); diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs index 3f61d9a..560e6c4 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs @@ -215,9 +215,39 @@ namespace OpenSim.Services.Connectors sendData[kvp.Key] = kvp.Value.ToString(); } - return SendAndGetBoolReply(sendData); + if (SendAndGetReply(sendData) != null) + return true; + else + return false; } + /// + /// Create user remotely. Note this this is not part of the IUserAccountsService + /// + /// + /// + /// + /// + /// + /// + public virtual UserAccount CreateUser(string first, string last, string password, string email, UUID scopeID) + { + Dictionary sendData = new Dictionary(); + //sendData["SCOPEID"] = scopeID.ToString(); + sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "createuser"; + + sendData["FirstName"] = first; + sendData["LastName"] = last; + sendData["Password"] = password; + if (!string.IsNullOrEmpty(email)) + sendData["Email"] = first; + sendData["ScopeID"] = scopeID.ToString(); + + return SendAndGetReply(sendData); + } + private UserAccount SendAndGetReply(Dictionary sendData) { string reply = string.Empty; @@ -260,7 +290,7 @@ namespace OpenSim.Services.Connectors { string reqString = ServerUtils.BuildQueryString(sendData); string uri = m_ServerURI + "/accounts"; - // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString); + //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString); try { string reply = SynchronousRestFormsRequester.MakeRequest("POST", @@ -269,6 +299,7 @@ namespace OpenSim.Services.Connectors m_Auth); if (reply != string.Empty) { + //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: reply = {0}", reply); Dictionary replyData = ServerUtils.ParseXmlResponse(reply); if (replyData.ContainsKey("result")) diff --git a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini deleted file mode 100644 index 453e17e..0000000 --- a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini +++ /dev/null @@ -1,33 +0,0 @@ -; * Run a ROBUST server shell like this, from bin: -; * $ OpenSim.Server.exe -inifile ../OpenSim/Tests/Clients/Presence/OpenSim.Server.ini -; * -; * Then run this client like this, from bin: -; * $ OpenSim.Tests.Clients.UserAccountClient.exe -; * -; * - -[Startup] -ServiceConnectors = "OpenSim.Server.Handlers.dll:UserAccountServiceConnector" - -; * This is common for all services, it's the network setup for the entire -; * server instance -; * -[Network] -port = 8003 - -; * The following are for the remote console -; * They have no effect for the local or basic console types -; * Leave commented to diable logins to the console -;ConsoleUser = Test -;ConsolePass = secret - -; * As an example, the below configuration precisely mimicks the legacy -; * asset server. It is read by the asset IN connector (defined above) -; * and it then loads the OUT connector (a local database module). That, -; * in turn, reads the asset loader and database connection information -; * -[UserAccountService] - LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" - StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" - diff --git a/OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs b/OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs deleted file mode 100644 index 1e0a35b..0000000 --- a/OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using log4net; -using log4net.Appender; -using log4net.Layout; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors; - -namespace OpenSim.Tests.Clients.PresenceClient -{ - public class UserAccountsClient - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - public static void Main(string[] args) - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - - string serverURI = "http://127.0.0.1:8003"; - UserAccountServicesConnector m_Connector = new UserAccountServicesConnector(serverURI); - - UUID user1 = UUID.Random(); - string first = "Completely"; - string last = "Clueless"; - string email = "foo@bar.com"; - - //UserAccount account = new UserAccount(user1); - //account.ScopeID = UUID.Zero; - //account.FirstName = first; - //account.LastName = last; - //account.Email = email; - //account.ServiceURLs = new Dictionary(); - //account.ServiceURLs.Add("InventoryServerURI", "http://cnn.com"); - //account.ServiceURLs.Add("AssetServerURI", "http://cnn.com"); - - //bool success = m_Connector.StoreUserAccount(account); - //if (success) - // m_log.InfoFormat("[USER CLIENT]: Successfully created account for user {0} {1}", account.FirstName, account.LastName); - //else - // m_log.InfoFormat("[USER CLIENT]: failed to create user {0} {1}", account.FirstName, account.LastName); - - //System.Console.WriteLine("\n"); - - //account = m_Connector.GetUserAccount(UUID.Zero, user1); - //if (account == null) - // m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by UUID for {0}", user1); - //else - //{ - // m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}", - // account.PrincipalID, account.FirstName, account.LastName, account.Email); - // foreach (KeyValuePair kvp in account.ServiceURLs) - // m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value); - //} - - //System.Console.WriteLine("\n"); - - UserAccount account = m_Connector.GetUserAccount(UUID.Zero, first, last); - if (account == null) - m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by name "); - else - { - m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}", - account.PrincipalID, account.FirstName, account.LastName, account.Email); - foreach (KeyValuePair kvp in account.ServiceURLs) - m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value); - } - - System.Console.WriteLine("\n"); - account = m_Connector.GetUserAccount(UUID.Zero, email); - if (account == null) - m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by email"); - else - { - m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}", - account.PrincipalID, account.FirstName, account.LastName, account.Email); - foreach (KeyValuePair kvp in account.ServiceURLs) - m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value); - } - - System.Console.WriteLine("\n"); - account = m_Connector.GetUserAccount(UUID.Zero, user1); - if (account == null) - m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by UUID for {0}", user1); - else - { - m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}", - account.PrincipalID, account.FirstName, account.LastName, account.Email); - foreach (KeyValuePair kvp in account.ServiceURLs) - m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value); - } - - System.Console.WriteLine("\n"); - account = m_Connector.GetUserAccount(UUID.Zero, "DoesNot", "Exist"); - if (account == null) - m_log.InfoFormat("[USER CLIENT]: Unable to retrieve account 'DoesNot Exist'"); - else - { - m_log.InfoFormat("[USER CLIENT]: Account 'DoesNot Exist' retrieved correctly. REALLY??? userID={0}; FirstName={1}; LastName={2}; Email={3}", - account.PrincipalID, account.FirstName, account.LastName, account.Email); - foreach (KeyValuePair kvp in account.ServiceURLs) - m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value); - } - } - - } -} diff --git a/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs new file mode 100644 index 0000000..2f92123 --- /dev/null +++ b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs @@ -0,0 +1,81 @@ +/* + * 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 System.Collections.Generic; +using System.Text; +using System.Reflection; + +using OpenMetaverse; +using NUnit.Framework; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors; + +namespace Robust.Tests +{ + [TestFixture] + public class UserAccountsClient + { + [Test] + public void UserAccounts_001() + { + UserAccountServicesConnector m_Connector = new UserAccountServicesConnector(DemonServer.Address); + + string first = "Completely"; + string last = "Clueless"; + string email = "foo@bar.com"; + + UserAccount account = m_Connector.CreateUser(first, last, "123", email, UUID.Zero); + Assert.IsNotNull(account, "Failed to create account " + first + " " + last); + UUID user1 = account.PrincipalID; + + account = m_Connector.GetUserAccount(UUID.Zero, user1); + Assert.NotNull(account, "Failed to retrieve account for user id " + user1); + Assert.AreEqual(account.FirstName, first, "First name does not match"); + Assert.AreEqual(account.LastName, last, "Last name does not match"); + + account = m_Connector.GetUserAccount(UUID.Zero, first, last); + Assert.IsNotNull(account, "Failed to retrieve account for user " + first + " " + last); + Assert.AreEqual(account.FirstName, first, "First name does not match (bis)"); + Assert.AreEqual(account.LastName, last, "Last name does not match (bis)"); + + account.Email = "user@example.com"; + bool success = m_Connector.StoreUserAccount(account); + Assert.IsTrue(success, "Failed to store account"); + + account = m_Connector.GetUserAccount(UUID.Zero, user1); + Assert.NotNull(account, "Failed to retrieve account for user id " + user1); + Assert.AreEqual(account.Email, "user@example.com", "Incorrect email"); + + account = m_Connector.GetUserAccount(UUID.Zero, "DoesNot", "Exist"); + Assert.IsNull(account, "Account DoesNot Exit must not be there"); + } + + } +} -- cgit v1.1 From aefed571587a620948ef283411d71732a10a3522 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 12 May 2015 08:55:32 -0700 Subject: One more test in UserAccountsClient. --- OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs index 2f92123..2c327e8 100644 --- a/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs +++ b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs @@ -67,7 +67,7 @@ namespace Robust.Tests account.Email = "user@example.com"; bool success = m_Connector.StoreUserAccount(account); - Assert.IsTrue(success, "Failed to store account"); + Assert.IsTrue(success, "Failed to store existing account"); account = m_Connector.GetUserAccount(UUID.Zero, user1); Assert.NotNull(account, "Failed to retrieve account for user id " + user1); @@ -75,6 +75,10 @@ namespace Robust.Tests account = m_Connector.GetUserAccount(UUID.Zero, "DoesNot", "Exist"); Assert.IsNull(account, "Account DoesNot Exit must not be there"); + + account = new UserAccount(UUID.Zero, "DoesNot", "Exist", "xxx@xxx.com"); + success = m_Connector.StoreUserAccount(account); + Assert.IsFalse(success, "Storing a non-existing account must fail"); } } -- cgit v1.1 From d52f58a7339aba40035f9bcc1f5b26232c714c48 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 12 May 2015 19:54:25 +0100 Subject: Disable the "show threadpool calls active" console command for now. Whilst this can be very useful to identify threads held too long by incoming packet processing, it can also be very misleading as the count updates are not atomic (race conditions lead to growth in numbers over time). This could be solved by making the counts volatile but I don't currently have time to assess the performance impact, though it's almost certainly negligible. If anybody else wants to do that and re-enable this command then please feel free. --- OpenSim/Framework/Servers/ServerBase.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index c22c119..e403ba0 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -292,11 +292,11 @@ namespace OpenSim.Framework.Servers + " 3 = full stack trace, including common threads\n", HandleDebugThreadpoolLevel); - m_console.Commands.AddCommand( - "Debug", false, "show threadpool calls active", - "show threadpool calls active", - "Show details about threadpool calls that are still active (currently waiting or in progress)", - HandleShowThreadpoolCallsActive); +// m_console.Commands.AddCommand( +// "Debug", false, "show threadpool calls active", +// "show threadpool calls active", +// "Show details about threadpool calls that are still active (currently waiting or in progress)", +// HandleShowThreadpoolCallsActive); m_console.Commands.AddCommand( "Debug", false, "show threadpool calls complete", -- cgit v1.1 From d348f871612c5f241f33885604391d1f30a416bc Mon Sep 17 00:00:00 2001 From: Magnuz Binder Date: Sun, 10 May 2015 20:01:50 +0200 Subject: Patch llCastRay fully simplified to V3. --- .../Shared/Api/Implementation/LSL_Api.cs | 429 +++++++++++---------- 1 file changed, 217 insertions(+), 212 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c90f015..089a5a8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -221,15 +221,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected float m_primSafetyCoeffX = 2.414214f; protected float m_primSafetyCoeffY = 2.414214f; protected float m_primSafetyCoeffZ = 1.618034f; + protected bool m_useCastRayV3 = false; protected float m_floatToleranceInCastRay = 0.000001f; protected float m_floatTolerance2InCastRay = 0.0001f; + protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; + protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; + protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; + protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; protected int m_maxHitsInCastRay = 16; protected int m_maxHitsPerPrimInCastRay = 16; protected int m_maxHitsPerObjectInCastRay = 16; protected bool m_detectExitsInCastRay = false; protected bool m_filterPartsInCastRay = false; protected bool m_doAttachmentsInCastRay = false; - protected bool m_useCastRayV1 = true; //An array of HTTP/1.1 headers that are not allowed to be used //as custom headers by llHTTPRequest. @@ -336,15 +340,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); + m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); + m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); + m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); + m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); + m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); - m_useCastRayV1 = lslConfig.GetBoolean("UseLlCastRayV1", m_useCastRayV1); } IConfig smtpConfig = seConfigSource.Configs["SMTP"]; @@ -13811,8 +13819,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return contacts[0]; } - public LSL_List llCastRayV1(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) { + // Use llCastRay V3 if configured + if (m_useCastRayV3) + return llCastRayV3(start, end, options); + LSL_List list = new LSL_List(); m_host.AddScriptLPS(1); @@ -14003,29 +14015,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Full implementation of llCastRay similar to SL 2015-04-21. + /// Implementation of llCastRay similar to SL 2015-04-21. /// http://wiki.secondlife.com/wiki/LlCastRay /// Uses pure geometry, bounding shapes, meshing and no physics /// for prims, sculpts, meshes, avatars and terrain. /// Implements all flags, reject types and data flags. /// Can handle both objects/groups and prims/parts, by config. - /// May give poor results with multi-part meshes where "root" - /// part doesn't dominate, owing to "guessed" bounding boxes. - /// May sometimes be inaccurate owing to calculation precision - /// and a bug in libopenmetaverse PrimMesher. + /// May sometimes be inaccurate owing to calculation precision, + /// meshing detail level and a bug in libopenmetaverse PrimMesher. /// - public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) { - // Use llCastRay v1 if configured - if (m_useCastRayV1) - return llCastRayV1(start, end, options); - // Initialize m_host.AddScriptLPS(1); List rayHits = new List(); LSL_List result = new LSL_List(); float tol = m_floatToleranceInCastRay; - float tol2 = m_floatTolerance2InCastRay; + Vector3 pos1Ray = start; + Vector3 pos2Ray = end; // Get input options int rejectTypes = 0; @@ -14054,25 +14061,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); // Calculate some basic parameters - Vector3 ray = end - start; - float rayLength = ray.Length(); + Vector3 vecRay = pos2Ray - pos1Ray; + float rayLength = vecRay.Length(); - // Try to get a mesher and return failure if none or degenerate ray + // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits IRendering primMesher = null; List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); - if (renderers.Count < 1 || rayLength < tol) + if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) { result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); return result; } primMesher = RenderingLoader.LoadRenderer(renderers[0]); - // Used to translate and rotate world so ray is along negative Z axis from origo and - // calculations mostly simplified to a 2D projecttion on the X-Y plane - Vector3 posProj = new Vector3(-start); - Quaternion rotProj = Vector3.RotationBetween(ray, new Vector3(0.0f, 0.0f, -1.0f)); - Quaternion rotBack = Quaternion.Inverse(rotProj); - // Iterate over all objects/groups and prims/parts in region World.ForEachSOG( delegate(SceneObjectGroup group) @@ -14115,51 +14116,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!doPart) continue; } - // Parse prim/part if passed filters - // Estimate bounding box from size box - Vector3 scaleSafe = part.Scale; - if (!part.Shape.SculptEntry) - scaleSafe = scaleSafe * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); + // Parse prim/part and project ray if passed filters + Vector3 scalePart = part.Scale; + Vector3 posPart = part.GetWorldPosition(); + Quaternion rotPart = part.GetWorldRotation(); + Quaternion rotPartInv = Quaternion.Inverse(rotPart); + Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; + Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; - // Filter parts by bounding shapes - Vector3 posPartRel = part.GetWorldPosition() + posProj; - Vector3 posPartProj = posPartRel * rotProj; - if (InBoundingShapes(ray, rayLength, scaleSafe, posPartRel, posPartProj, rotProj)) + // Filter parts by shape bounding boxes + Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); + if (!part.Shape.SculptEntry) + shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); + shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); + if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) { // Prepare data needed to check for ray hits RayTrans rayTrans = new RayTrans(); rayTrans.PartId = part.UUID; rayTrans.GroupId = part.ParentGroup.UUID; rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; - rayTrans.Scale = part.Scale; - rayTrans.PositionPartProj = posPartProj; - rayTrans.PositionProj = posProj; - rayTrans.RotationPartProj = rotProj * part.GetWorldRotation(); - rayTrans.RotationBack = rotBack; - rayTrans.NeedsEnds = true; - rayTrans.RayLength = rayLength; - rayTrans.Tolerance = tol; - rayTrans.Tolerance2 = tol2; + rayTrans.ScalePart = scalePart; + rayTrans.PositionPart = posPart; + rayTrans.RotationPart = rotPart; + rayTrans.ShapeNeedsEnds = true; + rayTrans.Position1Ray = pos1Ray; + rayTrans.Position1RayProj = pos1RayProj; + rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; // Make an OMV prim to be able to mesh part - Primitive omvPrim = part.Shape.ToOmvPrimitive(posPartProj, rayTrans.RotationPartProj); + Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); byte[] sculptAsset = null; if (omvPrim.Sculpt != null) sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); + FacetedMesh mesh = null; - // When part is mesh, get and check mesh + // When part is mesh, get mesh and check for hits if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); - FacetedMesh mesh = null; - FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); + FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); meshAsset = null; - AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); - mesh = null; } - // When part is sculpt, create and check mesh + // When part is sculpt, create mesh and check for hits // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) { @@ -14169,15 +14170,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Image sculpt = imgDecoder.DecodeToImage(sculptAsset); if (sculpt != null) { - SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); + mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); sculpt.Dispose(); - AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); - mesh = null; } } } - // When part is prim, create and check mesh + // When part is prim, create mesh and check for hits else if (omvPrim.Sculpt == null) { if ( @@ -14186,12 +14185,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api omvPrim.PrimData.PathSkew == 0.0 && omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 ) - rayTrans.NeedsEnds = false; - SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); - AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); - mesh = null; + rayTrans.ShapeNeedsEnds = false; + mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); } + // Check mesh for ray hits + AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); + mesh = null; } } } @@ -14205,38 +14205,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.ForEachRootScenePresence( delegate (ScenePresence sp) { - // Parse avatar - // Get bounding box Vector3 lower; Vector3 upper; BoundingBoxOfScenePresence(sp, out lower, out upper); - Vector3 scale = upper - lower; - - // Filter avatars by bounding shapes - Vector3 posPartRel = sp.AbsolutePosition + posProj + (lower + upper) * 0.5f * sp.Rotation; - Vector3 posPartProj = posPartRel * rotProj; - if (InBoundingShapes(ray, rayLength, scale, posPartRel, posPartProj, rotProj)) + // Parse avatar + Vector3 scalePart = upper - lower; + Vector3 posPart = sp.AbsolutePosition; + Quaternion rotPart = sp.GetWorldRotation(); + Quaternion rotPartInv = Quaternion.Inverse(rotPart); + posPart = posPart + (lower + upper) * 0.5f * rotPart; + // Project ray + Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; + Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; + + // Filter avatars by shape bounding boxes + Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol); + if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) { // Prepare data needed to check for ray hits RayTrans rayTrans = new RayTrans(); rayTrans.PartId = sp.UUID; rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; - rayTrans.Scale = scale; - rayTrans.PositionPartProj = posPartProj; - rayTrans.PositionProj = posProj; - rayTrans.RotationPartProj = rotProj * sp.Rotation; - rayTrans.RotationBack = rotBack; - rayTrans.NeedsEnds = false; - rayTrans.RayLength = rayLength; - rayTrans.Tolerance = tol; - rayTrans.Tolerance2 = tol2; + rayTrans.ScalePart = scalePart; + rayTrans.PositionPart = posPart; + rayTrans.RotationPart = rotPart; + rayTrans.ShapeNeedsEnds = false; + rayTrans.Position1Ray = pos1Ray; + rayTrans.Position1RayProj = pos1RayProj; + rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; // Make OMV prim, create and check mesh - Primitive omvPrim = MakeOpenMetaversePrim(scale, posPartProj, rayTrans.RotationPartProj, ScriptBaseClass.PRIM_TYPE_SPHERE); - SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); - AddRayInSimpleMesh(mesh, rayTrans, ref rayHits); + PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); + prim.Scale = scalePart; + Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); + FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay); + AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); mesh = null; } } @@ -14248,32 +14253,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // Parse terrain - // Mesh terrain and check projected bounding box - Vector3 posPartProj = posProj * rotProj; - Quaternion rotPartProj = rotProj; + // Mesh terrain and check bounding box Vector3 lower; Vector3 upper; - List triangles = TrisFromHeightmapUnderRay(start, end, out lower, out upper); - Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); - Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); - int dummy = 0; - AddBoundingBoxOfSimpleBox(lower, upper, posPartProj, rotPartProj, true, ref lowerBox, ref upperBox, ref dummy); - if (lowerBox.X <= tol && lowerBox.Y <= tol && lowerBox.Z <= tol && upperBox.X >= -tol && upperBox.Y >= -tol && upperBox.Z >= -rayLength - tol) + List triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper); + lower.Z -= tol; + upper.Z += tol; + if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z)) { // Prepare data needed to check for ray hits RayTrans rayTrans = new RayTrans(); rayTrans.PartId = UUID.Zero; rayTrans.GroupId = UUID.Zero; rayTrans.Link = 0; - rayTrans.Scale = new Vector3 (1.0f, 1.0f, 1.0f); - rayTrans.PositionPartProj = posPartProj; - rayTrans.PositionProj = posProj; - rayTrans.RotationPartProj = rotPartProj; - rayTrans.RotationBack = rotBack; - rayTrans.NeedsEnds = true; - rayTrans.RayLength = rayLength; - rayTrans.Tolerance = tol; - rayTrans.Tolerance2 = tol2; + rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f); + rayTrans.PositionPart = Vector3.Zero; + rayTrans.RotationPart = Quaternion.Identity; + rayTrans.ShapeNeedsEnds = true; + rayTrans.Position1Ray = pos1Ray; + rayTrans.Position1RayProj = pos1Ray; + rayTrans.VectorRayProj = vecRay; // Check mesh AddRayInTris(triangles, rayTrans, ref rayHits); @@ -14358,15 +14357,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public UUID PartId; public UUID GroupId; public int Link; - public Vector3 Scale; - public Vector3 PositionPartProj; - public Vector3 PositionProj; - public Quaternion RotationPartProj; - public Quaternion RotationBack; - public bool NeedsEnds; - public float RayLength; - public float Tolerance; - public float Tolerance2; + public Vector3 ScalePart; + public Vector3 PositionPart; + public Quaternion RotationPart; + public bool ShapeNeedsEnds; + public Vector3 Position1Ray; + public Vector3 Position1RayProj; + public Vector3 VectorRayProj; } /// @@ -14383,21 +14380,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Helper to parse SimpleMesh for ray hits. + /// Helper to check if a ray intersects a shape bounding box. /// - private void AddRayInSimpleMesh(SimpleMesh mesh, RayTrans rayTrans, ref List rayHits) - { - if (mesh != null) + private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) + { + // Skip if ray can't intersect bounding box; + Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj); + Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj); + if ( + rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z || + rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z + ) + return false; + + // Check if ray intersect any bounding box side + int sign = 0; + float dist = 0.0f; + Vector3 posProj = Vector3.Zero; + Vector3 vecRayProj = pos2RayProj - pos1RayProj; + + // Check both X sides unless ray is parallell to them + if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay) + { + for (sign = -1; sign <= 1; sign += 2) + { + dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X; + posProj = pos1RayProj + vecRayProj * dist; + if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z) + return true; + } + } + + // Check both Y sides unless ray is parallell to them + if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay) { - for (int i = 0; i < mesh.Indices.Count; i += 3) + for (sign = -1; sign <= 1; sign += 2) { - Tri triangle = new Tri(); - triangle.p1 = mesh.Vertices[mesh.Indices[i]].Position; - triangle.p2 = mesh.Vertices[mesh.Indices[i + 1]].Position; - triangle.p3 = mesh.Vertices[mesh.Indices[i + 2]].Position; - AddRayInTri(triangle, rayTrans, ref rayHits); + dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y; + posProj = pos1RayProj + vecRayProj * dist; + if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z) + return true; } } + + // Check both Z sides unless ray is parallell to them + if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay) + { + for (sign = -1; sign <= 1; sign += 2) + { + dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z; + posProj = pos1RayProj + vecRayProj * dist; + if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y) + return true; + } + } + + // No hits on bounding box so return false + return false; } /// @@ -14409,7 +14448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (Face face in mesh.Faces) { - for (int i = 0; i /// Helper to add ray hit in a Tri (triangle). /// - private void AddRayInTri(Tri triangle, RayTrans rayTrans, ref List rayHits) + private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List rayHits) { // Check for hit in triangle - float distance; - Vector3 posHit; - Vector3 normal; - if (HitRayInTri(triangle, rayTrans, out distance, out posHit, out normal)) - { - // Project hit part back to normal coordinate system - Vector3 posPart = rayTrans.PositionPartProj * rayTrans.RotationBack - rayTrans.PositionProj; - // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) faces plane through shape center - if (Math.Abs(Vector3.Dot(posPart, normal) - Vector3.Dot(posHit, normal)) < rayTrans.Tolerance && !rayTrans.NeedsEnds) + Vector3 posHitProj; + Vector3 normalProj; + if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj)) + { + // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center + if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds) return; - // Remove duplicate hits at triangle edges and intersections + + // Transform hit and normal to region coordinate system + Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart; + Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart); + + // Remove duplicate hits at triangle intersections + float distance = Vector3.Distance(rayTrans.Position1Ray, posHit); for (int i = rayHits.Count - 1; i >= 0; i--) { - if (rayHits[i].PartId == rayTrans.PartId && Math.Abs(rayHits[i].Distance - distance) < rayTrans.Tolerance2) + if (rayHits[i].PartId != rayTrans.PartId) + break; + if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay) return; } @@ -14468,76 +14512,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Helper to find ray hit in a Tri (triangle). + /// Helper to find ray hit in triangle /// - private bool HitRayInTri(Tri triangle, RayTrans rayTrans, out float distance, out Vector3 posHit, out Vector3 normal) + bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj) { - // Initialize - distance = 0.0f; - posHit = Vector3.Zero; - normal = Vector3.Zero; - float tol = rayTrans.Tolerance; - - // Project triangle on X-Y plane - Vector3 pos1 = triangle.p1 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; - Vector3 pos2 = triangle.p2 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; - Vector3 pos3 = triangle.p3 * rayTrans.Scale * rayTrans.RotationPartProj + rayTrans.PositionPartProj; - - // Check if ray/origo inside triangle bounding rectangle - Vector3 lower = Vector3.Min(pos1, Vector3.Min(pos2, pos3)); - Vector3 upper = Vector3.Max(pos1, Vector3.Max(pos2, pos3)); - if (lower.X > tol || lower.Y > tol || lower.Z > tol || upper.X < -tol || upper.Y < -tol || upper.Z < -rayTrans.RayLength - tol) - return false; + float tol = m_floatToleranceInCastRay; + posHitProj = Vector3.Zero; + + // Calculate triangle edge vectors + Vector3 vec1Proj = triProj.p2 - triProj.p1; + Vector3 vec2Proj = triProj.p3 - triProj.p2; + Vector3 vec3Proj = triProj.p1 - triProj.p3; - // Check if ray/origo inside every edge or reverse "outside" every edge on exit - float dist; - bool inside = true; - bool outside = true; - Vector3 vec1 = pos2 - pos1; - dist = pos1.X * vec1.Y - pos1.Y * vec1.X; - if (dist < -tol) - inside = false; - if (dist > tol) - outside = false; - Vector3 vec2 = pos3 - pos2; - dist = pos2.X * vec2.Y - pos2.Y * vec2.X; - if (dist < -tol) - inside = false; - if (dist > tol) - outside = false; - Vector3 vec3 = pos1 - pos3; - dist = pos3.X * vec3.Y - pos3.Y * vec3.X; - if (dist < -tol) - inside = false; - if (dist > tol) - outside = false; - - // Skip if ray/origo outside - if (!inside && !(outside && m_detectExitsInCastRay)) + // Calculate triangle normal + normalProj = Vector3.Cross(vec1Proj, vec2Proj); + + // Skip if degenerate triangle or ray parallell with triangle plane + float divisor = Vector3.Dot(vecRayProj, normalProj); + if (Math.Abs(divisor) < tol) return false; - // Calculate normal - Vector3 normalProj = Vector3.Cross(vec1, vec2); - float normalLength = normalProj.Length(); - // Skip if degenerate triangle - if (normalLength < tol) + // Skip if exit and not configured to detect + if (divisor > tol && !m_detectExitsInCastRay) return false; - normalProj = normalProj / normalLength; - // Skip if ray parallell to triangle plane - if (Math.Abs(normalProj.Z) < tol) + + // Skip if outside ray ends + float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor; + if (distanceProj < -tol || distanceProj > 1 + tol) return false; - // Calculate distance - distance = Vector3.Dot(normalProj, pos2) / normalProj.Z * -1.0f; - // Skip if outside ray - if (distance < -tol || distance > rayTrans.RayLength + tol) + // Calculate hit position in triangle + posHitProj = pos1RayProj + vecRayProj * distanceProj; + + // Skip if outside triangle bounding box + Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3); + Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3); + if ( + posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol || + posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol + ) return false; - // Calculate projected hit position - Vector3 posHitProj = new Vector3(0.0f, 0.0f, -distance); - // Project hit back to normal coordinate system - posHit = posHitProj * rayTrans.RotationBack - rayTrans.PositionProj; - normal = normalProj * rayTrans.RotationBack; + // Skip if outside triangle + if ( + Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol || + Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol || + Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol + ) + return false; + + // Return hit return true; } @@ -14660,24 +14684,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api y = Util.Clamp(yInt+1, 0, World.Heightmap.Height - 1); Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); // Adjust bounding box - zLower = Math.Min(zLower, pos1.Z); - zUpper = Math.Max(zUpper, pos1.Z); + zLower = Math.Min(zLower, pos2.Z); + zUpper = Math.Max(zUpper, pos2.Z); // Corner 3 of 1x1 rectangle x = Util.Clamp(xInt, 0, World.Heightmap.Width - 1); y = Util.Clamp(yInt, 0, World.Heightmap.Height - 1); Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); // Adjust bounding box - zLower = Math.Min(zLower, pos1.Z); - zUpper = Math.Max(zUpper, pos1.Z); + zLower = Math.Min(zLower, pos3.Z); + zUpper = Math.Max(zUpper, pos3.Z); // Corner 4 of 1x1 rectangle x = Util.Clamp(xInt+1, 0, World.Heightmap.Width - 1); y = Util.Clamp(yInt, 0, World.Heightmap.Height - 1); Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); // Adjust bounding box - zLower = Math.Min(zLower, pos1.Z); - zUpper = Math.Max(zUpper, pos1.Z); + zLower = Math.Min(zLower, pos4.Z); + zUpper = Math.Max(zUpper, pos4.Z); // Add triangle 1 Tri triangle1 = new Tri(); @@ -14695,25 +14719,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Helper to check if a ray intersects bounding shapes. - /// - private bool InBoundingShapes(Vector3 ray, float rayLength, Vector3 scale, Vector3 posPartRel, Vector3 posPartProj, Quaternion rotProj) - { - float tol = m_floatToleranceInCastRay; - - // Check if ray intersects projected bounding box - Vector3 lowerBox = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); - Vector3 upperBox = new Vector3(float.MinValue, float.MinValue, float.MinValue); - int dummy = 0; - AddBoundingBoxOfSimpleBox(scale * -0.5f, scale * 0.5f, posPartProj, rotProj, true, ref lowerBox, ref upperBox, ref dummy); - if (lowerBox.X > tol || lowerBox.Y > tol || lowerBox.Z > tol || upperBox.X < -tol || upperBox.Y < -tol || upperBox.Z < -rayLength - tol) - return false; - - // Passed bounding shape filters, so return true - return true; - } - - /// /// Helper to get link number for a UUID. /// private int UUID2LinkNumber(SceneObjectPart part, UUID id) -- cgit v1.1 From cb586d11582fa2641fe99edc6367edc800af0ba0 Mon Sep 17 00:00:00 2001 From: AliciaRaven Date: Mon, 4 May 2015 04:10:08 +0100 Subject: Enable grab feature (Ctrl+Drag) for non-physical link-sets and add code to handle spin (Ctrl+Shift+Drag) This patch fixes permission issues with dragging scripted objects. As on LL grid, scripted prims can not be dragged. Also after dragging, the group was not marked as updated. This meant that after the region was restarted the group would revert to its original position. This version fixes issues where scripts in child prims were not detected and also blocks grab for attachments. Signed-off-by: BlueWall --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0a1a226..866a43c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2672,20 +2672,27 @@ namespace OpenSim.Region.Framework.Scenes } else { - //NonPhysicalGrabMovement(pos); + NonPhysicalGrabMovement(pos); } } else { - //NonPhysicalGrabMovement(pos); + NonPhysicalGrabMovement(pos); } } } + /// + /// Apply possition for grabbing non-physical linksets (Ctrl+Drag) + /// This MUST be blocked for linksets that contain touch scripts because the viewer triggers grab on the touch + /// event (Viewer Bug?) This would allow anyone to drag a linkset with a touch script. SL behaviour is also to + /// block grab on prims with touch events. + /// + /// New Position public void NonPhysicalGrabMovement(Vector3 pos) { - AbsolutePosition = pos; - m_rootPart.SendTerseUpdateToAllClients(); + if(!IsAttachment && ScriptCount() == 0) + UpdateGroupPosition(pos); } /// @@ -2781,17 +2788,28 @@ namespace OpenSim.Region.Framework.Scenes } else { - //NonPhysicalSpinMovement(pos); + NonPhysicalSpinMovement(newOrientation); } } else { - //NonPhysicalSpinMovement(pos); + NonPhysicalSpinMovement(newOrientation); } } } /// + /// Apply rotation for spinning non-physical linksets (Ctrl+Shift+Drag) + /// As with dragging, scripted objects must be blocked from spinning + /// + /// New Rotation + private void NonPhysicalSpinMovement(Quaternion newOrientation) + { + if(!IsAttachment && ScriptCount() == 0) + UpdateGroupRotationR(newOrientation); + } + + /// /// Set the name of a prim /// /// -- cgit v1.1 From 3c2886cd7507890b03f1213ca280c4a505af52c3 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 13 May 2015 14:31:28 -0500 Subject: Adding back command to clear region's user cache --- .../UserManagement/UserManagementModule.cs | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index ba71dc5..7ecbd26 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #endregion ISharedRegionModule - + #region Event Handlers void EventManager_OnPrimsLoaded(Scene s) @@ -180,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement void HandleUUIDNameRequest(UUID uuid, IClientAPI client) { // m_log.DebugFormat( -// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", +// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", // uuid, remote_client.Name); if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) @@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // appear to clear this when the user asks it to clear the cache, but others may not. // // So to avoid clients - // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will + // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will // instead drop the request entirely. if (GetUser(uuid, out user)) { @@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement } // else // m_log.DebugFormat( -// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", +// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", // uuid, client.Name); }); } @@ -416,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e); userdata.ServerURLs = new Dictionary(); } - + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) return userdata.ServerURLs[serverType].ToString(); } @@ -620,7 +620,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement AddUser(id, string.Empty, string.Empty, string.Empty); } else - { + { string homeURL; string firstname = string.Empty; string lastname = string.Empty; @@ -676,7 +676,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement else { lock(m_UserCache) - { + { if(!m_UserCache.ContainsKey(id)) { UserData newUser = new UserData(); @@ -726,6 +726,21 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement "Show the bindings between user UUIDs and user names", String.Empty, HandleShowUsers); + + MainConsole.Instance.Commands.AddCommand("Users", true, + "reset user cache", + "reset user cache", + "reset user cache to allow changed settings to be applied", + String.Empty, + HandleResetUserCache); + } + + private void HandleResetUserCache(string module, string[] cmd) + { + lock(m_UserCache) + { + m_UserCache.Clear(); + } } private void HandleShowUser(string module, string[] cmd) -- cgit v1.1 From 6a48c87cd20e9df5ebdd2898872618455106be4c Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 13 May 2015 15:59:58 -0700 Subject: resolve possible nullref when sending appearance packet. Thanks to zadark for pointing this out. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 855342f..284c5fa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3747,6 +3747,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; + avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } -- cgit v1.1