From 086bf9f15db05ca2be1cf0dda24f8ee7a368988d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 9 Sep 2011 00:29:59 +0100 Subject: Save the default terrain texture UUIDs for a new region instead of leaving them as UUID.Zero. Leaving them at UUID.Zero meant that when a viewer 2 logged into a region that had been freshly created, it received UUID.Zero for these textures, and hence display the land as plain white. On a simulator restart, the problem would go away since when the database adapators loaded the new region settings, RegionSettings itself has code to use default textures instead of UUID.Zero. This commit resolves the problem by saving the default texture UUIDs instead of Zero. However, we currently have to do this in a roundabout way by resaving once the RegionSettings have been created by the database for the first time. This needless complexity should be addressed. This change will also have the effect of replacing any existing UUID.Zero terrain textures with the default ones. However, this shouldn't have any effect since the UUID.Zeros were already being replaced in memory with those same UUIDs. --- .../Handlers/GetTexture/GetTextureHandler.cs | 5 ++- OpenSim/Data/MySQL/MySQLSimulationData.cs | 1 - .../World/Estate/EstateManagementModule.cs | 5 +++ OpenSim/Region/Framework/Scenes/Scene.cs | 37 +++++++++++++++++++++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index 105a1e0..e1b4fe7 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -47,7 +47,6 @@ using Caps = OpenSim.Framework.Capabilities.Caps; namespace OpenSim.Capabilities.Handlers { - public class GetTextureHandler : BaseStreamHandler { private static readonly ILog m_log = @@ -67,7 +66,6 @@ namespace OpenSim.Capabilities.Handlers public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - // Try to parse the texture ID from the request URL NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); string textureStr = query.GetOne("texture_id"); @@ -85,6 +83,8 @@ namespace OpenSim.Capabilities.Handlers UUID textureID; if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) { +// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID); + string[] formats; if (format != null && format != string.Empty) { @@ -105,7 +105,6 @@ namespace OpenSim.Capabilities.Handlers if (FetchTexture(httpRequest, httpResponse, textureID, f)) break; } - } else { diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 96ecea6..6d14b82 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -1209,7 +1209,6 @@ namespace OpenSim.Data.MySQL return prim; } - /// /// Build a prim inventory item from the persisted data. /// diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index d0605e3..94c1417 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -968,6 +968,11 @@ namespace OpenSim.Region.CoreModules.World.Estate args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; + m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); + m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); + m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); + m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); + remoteClient.SendRegionHandshake(Scene.RegionInfo,args); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d3de37d..f86b3b6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -588,7 +588,42 @@ namespace OpenSim.Region.Framework.Scenes #region Region Settings // Load region settings - m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); + // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region. + // However, in this case, the default textures are not set in memory properly, so we need to do it here and + // resave. + // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new + // region is set up and avoid these gyrations. + RegionSettings rs = simDataService.LoadRegionSettings(m_regInfo.RegionID); + bool updatedTerrainTextures = false; + if (rs.TerrainTexture1 == UUID.Zero) + { + rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1; + updatedTerrainTextures = true; + } + + if (rs.TerrainTexture2 == UUID.Zero) + { + rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2; + updatedTerrainTextures = true; + } + + if (rs.TerrainTexture3 == UUID.Zero) + { + rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3; + updatedTerrainTextures = true; + } + + if (rs.TerrainTexture4 == UUID.Zero) + { + rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4; + updatedTerrainTextures = true; + } + + if (updatedTerrainTextures) + rs.Save(); + + m_regInfo.RegionSettings = rs; + if (estateDataService != null) m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); -- cgit v1.1 From 42790f021fd5d69ba10ac02d158681f3d299da80 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 9 Sep 2011 00:47:23 +0100 Subject: Fix unit tests from RegionSettings commit --- OpenSim/Data/Null/NullSimulationData.cs | 4 ++++ OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs index e8d733b..c33a6f2 100644 --- a/OpenSim/Data/Null/NullSimulationData.cs +++ b/OpenSim/Data/Null/NullSimulationData.cs @@ -59,19 +59,23 @@ namespace OpenSim.Data.Null public void StoreRegionSettings(RegionSettings rs) { } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { //This connector doesn't support the windlight module yet //Return default LL windlight settings return new RegionLightShareData(); } + public void RemoveRegionWindlightSettings(UUID regionID) { } + public void StoreRegionWindlightSettings(RegionLightShareData wl) { //This connector doesn't support the windlight module yet } + public RegionSettings LoadRegionSettings(UUID regionUUID) { return null; diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs index 2ea36da..79bb9c2 100644 --- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs @@ -163,6 +163,10 @@ namespace OpenSim.Data.Null { RegionSettings rs = null; m_regionSettings.TryGetValue(regionUUID, out rs); + + if (rs == null) + rs = new RegionSettings(); + return rs; } -- cgit v1.1 From 655935db49ad3a363426eef52f4aedba990cc9af Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 9 Sep 2011 01:00:41 +0100 Subject: Use a copy of the inventory items list to register users in the thread started by GetFolderContent(), to protect ourselves against callers modifying lists Hopefully this addresses http://opensimulator.org/mantis/view.php?id=5681 --- .../ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs | 5 ++++- .../Inventory/RemoteXInventoryServiceConnector.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index d3ef08d..1c83f8e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -188,8 +188,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory Util.FireAndForget(delegate { if (UserManager != null) - foreach (InventoryItemBase item in invCol.Items) + { + // Protect ourselves against the caller subsequently modifying the items list + foreach (InventoryItemBase item in new List(invCol.Items)) UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); + } }); return invCol; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index eb90774..c9c716c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -196,8 +196,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory Util.FireAndForget(delegate { if (UserManager != null) - foreach (InventoryItemBase item in invCol.Items) + { + // Protect ourselves against the caller subsequently modifying the items list + foreach (InventoryItemBase item in new List(invCol.Items)) UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); + } }); return invCol; -- cgit v1.1 From bea2e0f32bfd49d4ea92dd59c508327354f9c93f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 9 Sep 2011 22:50:54 +0100 Subject: Comment out the part of the load oar code that zeroes out prim sit target orientations and positions. The warning about these causing problems is very old and may no longer apply. Hopes to fix http://opensimulator.org/mantis/view.php?id=5680 --- OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | 4 ++-- OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 48130e7..587d260 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -284,8 +284,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; // And zap any troublesome sit target information - part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); - part.SitTargetPosition = new Vector3(0, 0, 0); +// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); +// part.SitTargetPosition = new Vector3(0, 0, 0); // Fix ownership/creator of inventory items // Not doing so results in inventory items diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index b185d9b..e798e5e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -318,6 +318,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); SceneObjectPart part1 = CreateSceneObjectPart1(); + + part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); + part1.SitTargetPosition = new Vector3(1, 2, 3); + SceneObjectGroup object1 = new SceneObjectGroup(part1); // Let's put some inventory items into our object @@ -390,6 +394,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); Assert.That( object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); + Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); + Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); -- cgit v1.1 From 28961dd1cfc21a90510faa33af6d3c1c6f8bc0af Mon Sep 17 00:00:00 2001 From: Micheil Merlin Date: Sun, 4 Sep 2011 12:21:29 -0500 Subject: llSetPrimitiveParams Prim type params precision errors --- .../Shared/Api/Implementation/LSL_Api.cs | 76 ++++++++++++++++------ .../ScriptEngine/Shared/Tests/LSL_ApiTest.cs | 58 ++++++++++------- 2 files changed, 90 insertions(+), 44 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 88e884d..cf8517d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6570,6 +6570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) { + float tempFloat; // Use in float expressions below to avoid byte cast precision issues. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && @@ -6651,8 +6652,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { twist.y = 1.0f; } - shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); - shapeBlock.PathTwist = (sbyte)(100 * twist.y); + // A fairly large precision error occurs for some calculations, + // if a float or double is directly cast to a byte or sbyte + // variable, in both .Net and Mono. In .Net, coding + // "(sbyte)(float)(some expression)" corrects the precision + // errors. But this does not work for Mono. This longer coding + // form of creating a tempoary float variable from the + // expression first, then casting that variable to a byte or + // sbyte, works for both .Net and Mono. These types of + // assignments occur in SetPrimtiveBlockShapeParams and + // SetPrimitiveShapeParams in support of llSetPrimitiveParams. + tempFloat = (float)(100.0d * twist.x); + shapeBlock.PathTwistBegin = (sbyte)tempFloat; + tempFloat = (float)(100.0d * twist.y); + shapeBlock.PathTwist = (sbyte)tempFloat; shapeBlock.ObjectLocalID = part.LocalId; @@ -6663,6 +6676,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Prim type box, cylinder and prism. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) { + float tempFloat; // Use in float expressions below to avoid byte cast precision issues. ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); @@ -6683,8 +6697,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { taper_b.y = 2f; } - shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); - shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); + tempFloat = (float)(100.0d * (2.0d - taper_b.x)); + shapeBlock.PathScaleX = (byte)tempFloat; + tempFloat = (float)(100.0d * (2.0d - taper_b.y)); + shapeBlock.PathScaleY = (byte)tempFloat; if (topshear.x < -0.5f) { topshear.x = -0.5f; @@ -6701,8 +6717,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { topshear.y = 0.5f; } - shapeBlock.PathShearX = (byte)(100 * topshear.x); - shapeBlock.PathShearY = (byte)(100 * topshear.y); + tempFloat = (float)(100.0d * topshear.x); + shapeBlock.PathShearX = (byte)tempFloat; + tempFloat = (float)(100.0d * topshear.y); + shapeBlock.PathShearY = (byte)tempFloat; part.Shape.SculptEntry = false; part.UpdateShape(shapeBlock); @@ -6752,6 +6770,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Prim type torus, tube and ring. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) { + float tempFloat; // Use in float expressions below to avoid byte cast precision issues. ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); @@ -6776,8 +6795,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { holesize.y = 0.5f; } - shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); - shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); + tempFloat = (float)(100.0d * (2.0d - holesize.x)); + shapeBlock.PathScaleX = (byte)tempFloat; + tempFloat = (float)(100.0d * (2.0d - holesize.y)); + shapeBlock.PathScaleY = (byte)tempFloat; if (topshear.x < -0.5f) { topshear.x = -0.5f; @@ -6794,8 +6815,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { topshear.y = 0.5f; } - shapeBlock.PathShearX = (byte)(100 * topshear.x); - shapeBlock.PathShearY = (byte)(100 * topshear.y); + tempFloat = (float)(100.0d * topshear.x); + shapeBlock.PathShearX = (byte)tempFloat; + tempFloat = (float)(100.0d * topshear.y); + shapeBlock.PathShearY = (byte)tempFloat; if (profilecut.x < 0f) { profilecut.x = 0f; @@ -6839,8 +6862,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { taper_a.y = 1f; } - shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); - shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); + tempFloat = (float)(100.0d * taper_a.x); + shapeBlock.PathTaperX = (sbyte)tempFloat; + tempFloat = (float)(100.0d * taper_a.y); + shapeBlock.PathTaperY = (sbyte)tempFloat; if (revolutions < 1f) { revolutions = 1f; @@ -6849,7 +6874,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { revolutions = 4f; } - shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); + tempFloat = 66.66667f * (revolutions - 1.0f); + shapeBlock.PathRevolutions = (byte)tempFloat; // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 if (radiusoffset < 0f) { @@ -6859,7 +6885,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { radiusoffset = 1f; } - shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); + tempFloat = 100.0f * radiusoffset; + shapeBlock.PathRadiusOffset = (sbyte)tempFloat; if (skew < -0.95f) { skew = -0.95f; @@ -6868,7 +6895,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { skew = 0.95f; } - shapeBlock.PathSkew = (sbyte)(100 * skew); + tempFloat = 100.0f * skew; + shapeBlock.PathSkew = (sbyte)tempFloat; part.Shape.SculptEntry = false; part.UpdateShape(shapeBlock); @@ -7681,10 +7709,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); // float revolutions - res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned - // byte is being used to represent the entire - // range of floating-point values from 1.0 - // through 4.0 (which is how SL does it). + res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); + // Slightly inaccurate, because an unsigned byte is being used to represent + // the entire range of floating-point values from 1.0 through 4.0 (which is how + // SL does it). + // + // Using these formulas to store and retrieve PathRevolutions, it is not + // possible to use all values between 1.00 and 4.00. For instance, you can't + // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you + // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them + // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar + // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. + // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value + // such as 1.10. So, SL must store and retreive the actual user input rather + // than only storing the encoded value. // float radiusoffset res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs index 8cd1e84..0cbad41 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6; private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; - private const double FLOAT_ACCURACY = 0.00005d; + private const float FLOAT_ACCURACY = 0.00005f; private LSL_Api m_lslApi; [SetUp] @@ -194,10 +194,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut - 0.80d, // Prim hollow + 0.80f, // Prim hollow new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple - 0.80d); // Prim hollow check + 0.80f); // Prim hollow check // Test a prism. CheckllSetPrimitiveParams( @@ -206,11 +206,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.90d, // Prim hollow + 0.90f, // Prim hollow new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear - 0.90d); // Prim hollow check + 0.90f); // Prim hollow check // Test a box. CheckllSetPrimitiveParams( @@ -219,11 +219,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScriptBaseClass.PRIM_TYPE_BOX, // Prim type ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.95d, // Prim hollow + 0.95f, // Prim hollow new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear - 0.95d); // Prim hollow check + 0.95f); // Prim hollow check // Test a tube. CheckllSetPrimitiveParams( @@ -232,16 +232,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.00d, // Prim hollow + 0.00f, // Prim hollow new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist - new LSL_Types.Vector3(1.0d, 0.5d, 0.0d), // Prim hole size - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear + new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size + // Expression for y selected to test precision problems during byte + // cast in SetPrimitiveShapeParams. + new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut - new LSL_Types.Vector3(-1.0d, 1.0d, 0.0d), // Prim taper - 1.0d, // Prim revolutions - 1.0d, // Prim radius - 0.0d, // Prim skew - 0.00d); // Prim hollow check + // Expression for y selected to test precision problems during sbyte + // cast in SetPrimitiveShapeParams. + new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper + 1.11f, // Prim revolutions + 0.88f, // Prim radius + 0.95f, // Prim skew + 0.00f); // Prim hollow check // Test a prism. CheckllSetPrimitiveParams( @@ -250,11 +254,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.95d, // Prim hollow - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist - new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper + 0.95f, // Prim hollow + // Expression for x selected to test precision problems during sbyte + // cast in SetPrimitiveShapeBlockParams. + new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist + // Expression for y selected to test precision problems during sbyte + // cast in SetPrimitiveShapeParams. + new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear - 0.70d); // Prim hollow check + 0.70f); // Prim hollow check // Test a sculpted prim. CheckllSetPrimitiveParams( @@ -268,8 +276,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests // Set prim params for a box, cylinder or prism and check results. public void CheckllSetPrimitiveParams(string primTest, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, - double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, - double primHollowCheck) + float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, + float primHollowCheck) { // Set the prim params. m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, @@ -297,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests // Set prim params for a sphere and check results. public void CheckllSetPrimitiveParams(string primTest, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, - double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, double primHollowCheck) + float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck) { // Set the prim params. m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, @@ -324,9 +332,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests // Set prim params for a torus, tube or ring and check results. public void CheckllSetPrimitiveParams(string primTest, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, - double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, + float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper, - double primRev, double primRadius, double primSkew, double primHollowCheck) + float primRev, float primRadius, float primSkew, float primHollowCheck) { // Set the prim params. m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, @@ -353,7 +361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut"); CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper"); Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim revolution fail"); + "TestllSetPrimitiveParams " + primTest + " prim revolutions fail"); Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY, "TestllSetPrimitiveParams " + primTest + " prim radius fail"); Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY, -- cgit v1.1 From 7cafc2e46eba6e46987ce6b41a8fecd2335222d3 Mon Sep 17 00:00:00 2001 From: Kevin Houlihan Date: Sun, 4 Sep 2011 14:46:52 +0100 Subject: Added a check to the CreateRegion method of the RemoteAdmin module that the specified user exists. A meaningful exception message is returned if the user is not found. Previously it was returning "Object not set..." --- .../RemoteController/RemoteAdminPlugin.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 93a6915..25ae3f1 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -709,6 +709,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController // ok, client wants us to use an explicit UUID // regardless of what the avatar name provided userID = new UUID((string) requestData["estate_owner_uuid"]); + + // Check that the specified user exists + Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; + IUserAccountService accountService = currentOrFirst.UserAccountService; + UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID); + + if (user == null) + throw new Exception("Specified user was not found."); } else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last")) { @@ -720,6 +728,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController IUserAccountService accountService = currentOrFirst.UserAccountService; UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, ownerFirst, ownerLast); + + // Check that the specified user exists + if (user == null) + throw new Exception("Specified user was not found."); + userID = user.PrincipalID; } else -- cgit v1.1 From 1dd904b78e723af8cb4340415a8f41dcd1054541 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 5 Sep 2011 12:45:02 +0300 Subject: Delay loading scripts until the scene has finished loading --- OpenSim/Region/Application/OpenSimBase.cs | 2 ++ .../Region/Framework/Interfaces/IScriptModule.cs | 5 +++++ OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 24 ++++++++++++++++++++-- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 3 +++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 00b080c..92e8ed1 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -411,6 +411,8 @@ namespace OpenSim scene.StartTimer(); + scene.StartScripts(); + return clientServer; } diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index d9752e6..b27b7da 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -52,5 +52,10 @@ namespace OpenSim.Region.Framework.Interfaces ArrayList GetScriptErrors(UUID itemID); void SaveAllState(); + + /// + /// Starts the processing threads. + /// + void StartProcessing(); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 4700c3b..9dcd10a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -57,11 +57,11 @@ namespace OpenSim.Region.Framework.Scenes protected AsyncInventorySender m_asyncInventorySender; /// - /// Start all the scripts in the scene which should be started. + /// Creates all the scripts in the scene which should be started. /// public void CreateScriptInstances() { - m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); + m_log.Info("[PRIM INVENTORY]: Creating scripts in scene"); EntityBase[] entities = Entities.GetEntities(); foreach (EntityBase group in entities) @@ -74,6 +74,26 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Lets the script engines start processing scripts. + /// + public void StartScripts() + { + m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); + + IScriptModule[] engines = RequestModuleInterfaces(); + if (engines != null) + { + foreach (IScriptModule engine in engines) + { + if (engine != null) + { + engine.StartProcessing(); + } + } + } + } + public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) { IMoneyModule money = RequestModuleInterface(); diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index c443669..55f373e 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -339,7 +339,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), new Object[] { m_SaveTime }); } + } + public void StartProcessing() + { m_ThreadPool.Start(); } -- cgit v1.1 From de28c9cd24372203c7375ea8e60bc4a2f295e8c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 10 Sep 2011 00:23:52 +0100 Subject: Stop the UserManagementModule logging every user it adds for now --- .../CoreModules/Framework/UserManagement/UserManagementModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index f7003db..bef0d69 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -363,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) m_UserCache[user.Id] = user; - m_log.DebugFormat( - "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", - user.Id, user.FirstName, user.LastName, user.HomeURL); +// m_log.DebugFormat( +// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", +// user.Id, user.FirstName, user.LastName, user.HomeURL); } //public void AddUser(UUID uuid, string userData) -- cgit v1.1 From 7531851bec552c07e997a4c8a934a23ddd3c7342 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 10 Sep 2011 00:45:50 +0100 Subject: reinstate the validation logging on teleport. A 'fail' of validation still doesn't prevent the actual teleport. --- .../Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ac13d5e..a4ef2b6 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -329,6 +329,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ParentID != (uint)0) sp.StandUp(); + sp.ValidateAttachments(); + // if (!sp.ValidateAttachments()) // { // sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); -- cgit v1.1 From 9c32b131fd0b156ada1c7e2d2107d6e1061da5e0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 10 Sep 2011 00:57:52 +0100 Subject: Add extra log information when attachments fail validation --- .../Framework/EntityTransfer/EntityTransferModule.cs | 16 +++++++++++----- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 10 +++++++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index a4ef2b6..8924c0a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -59,7 +59,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer get { return m_MaxTransferDistance; } set { m_MaxTransferDistance = value; } } - protected bool m_Enabled = false; protected Scene m_aScene; @@ -68,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private ExpiringCache> m_bannedRegions = new ExpiringCache>(); - #region ISharedRegionModule public Type ReplaceableInterface @@ -329,7 +327,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ParentID != (uint)0) sp.StandUp(); - sp.ValidateAttachments(); + if (!sp.ValidateAttachments()) + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", + sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); // if (!sp.ValidateAttachments()) // { @@ -941,7 +942,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// This Closes child agents on neighbouring regions /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// - protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) + protected ScenePresence CrossAgentToNewRegionAsync( + ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, + bool isFlying, string version) { ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); @@ -951,7 +954,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (neighbourRegion != null) { - agent.ValidateAttachments(); + if (!agent.ValidateAttachments()) + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", + agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); pos = pos + (agent.Velocity); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f231a39..18ad715 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3501,8 +3501,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// This is currently just being done for information. /// - public void ValidateAttachments() + public bool ValidateAttachments() { + bool validated = true; + lock (m_attachments) { // Validate @@ -3512,15 +3514,21 @@ namespace OpenSim.Region.Framework.Scenes { m_log.WarnFormat( "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name); + + validated = false; } else if (gobj.IsDeleted) { m_log.WarnFormat( "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted. Continuing", gobj.Name, gobj.UUID, Name); + + validated = false; } } } + + return validated; } /// -- cgit v1.1 From 728fd0b1b8e1c80f6961ec06efb34727645fdc3e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 10 Sep 2011 01:09:17 +0100 Subject: lock attachments when enumerating through them in ScenePresence.CopyTo(). May have some effect on http://opensimulator.org/mantis/view.php?id=5644 --- OpenSim/Framework/ChildAgentDataUpdate.cs | 1 - OpenSim/Region/Framework/Scenes/ScenePresence.cs | 44 +++++++++++++----------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 53ec166..5a4811e 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -441,7 +441,6 @@ namespace OpenSim.Framework args["controllers"] = controls; } - if ((CallbackURI != null) && (!CallbackURI.Equals(""))) args["callback_uri"] = OSD.FromString(CallbackURI); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 18ad715..d65d78d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3141,26 +3141,30 @@ namespace OpenSim.Region.Framework.Scenes catch { } // Attachment objects - if (m_attachments != null && m_attachments.Count > 0) - { - cAgent.AttachmentObjects = new List(); - cAgent.AttachmentObjectStates = new List(); -// IScriptModule se = m_scene.RequestModuleInterface(); - m_InTransitScriptStates.Clear(); - foreach (SceneObjectGroup sog in m_attachments) - { - // We need to make a copy and pass that copy - // because of transfers withn the same sim - ISceneObject clone = sog.CloneForNewScene(); - // Attachment module assumes that GroupPosition holds the offsets...! - ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos; - ((SceneObjectGroup)clone).IsAttachment = false; - cAgent.AttachmentObjects.Add(clone); - string state = sog.GetStateSnapshot(); - cAgent.AttachmentObjectStates.Add(state); - m_InTransitScriptStates.Add(state); - // Let's remove the scripts of the original object here - sog.RemoveScriptInstances(true); + lock (m_attachments) + { + if (m_attachments.Count > 0) + { + cAgent.AttachmentObjects = new List(); + cAgent.AttachmentObjectStates = new List(); + // IScriptModule se = m_scene.RequestModuleInterface(); + m_InTransitScriptStates.Clear(); + + foreach (SceneObjectGroup sog in m_attachments) + { + // We need to make a copy and pass that copy + // because of transfers withn the same sim + ISceneObject clone = sog.CloneForNewScene(); + // Attachment module assumes that GroupPosition holds the offsets...! + ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos; + ((SceneObjectGroup)clone).IsAttachment = false; + cAgent.AttachmentObjects.Add(clone); + string state = sog.GetStateSnapshot(); + cAgent.AttachmentObjectStates.Add(state); + m_InTransitScriptStates.Add(state); + // Let's remove the scripts of the original object here + sog.RemoveScriptInstances(true); + } } } } -- cgit v1.1 From 517932722bd73de85366b4752ce0fa65776672d3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 20:06:09 +0100 Subject: minor: put tags around some method doc --- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 77b1535..3acdaf8 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -43,11 +43,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// Gather uuids for a given entity. /// - /// + /// /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be /// retrieved to work out which assets it references). + /// public class UuidGatherer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -76,11 +77,11 @@ namespace OpenSim.Region.Framework.Scenes /// /// Gather all the asset uuids associated with the asset referenced by a given uuid /// - /// + /// /// This includes both those directly associated with /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained /// within this object). - /// + /// /// The uuid of the asset for which to gather referenced assets /// The type of the asset for the uuid given /// The assets gathered @@ -123,11 +124,11 @@ namespace OpenSim.Region.Framework.Scenes /// /// Gather all the asset uuids associated with a given object. /// - /// + /// /// This includes both those directly associated with /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained /// within this object). - /// + /// /// The scene object for which to gather assets /// The assets gathered public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids) -- cgit v1.1 From 7f318277f141a73207ec64f8521ba410a5743215 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Sun, 11 Sep 2011 20:52:35 +0300 Subject: When creating an OAR, optionally exclude objects according to their permissions --- CONTRIBUTORS.txt | 1 + OpenSim/Region/Application/OpenSim.cs | 10 +- .../Archiver/ArchiveWriteRequestPreparation.cs | 106 ++++++++++++++++++++- .../CoreModules/World/Archiver/ArchiverModule.cs | 1 + .../World/Permissions/PermissionsModule.cs | 89 ++++++++++------- .../Framework/Interfaces/IPermissionsModule.cs | 54 +++++++++++ 6 files changed, 217 insertions(+), 44 deletions(-) create mode 100644 OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 2fe8b46..239b884 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -117,6 +117,7 @@ what it is today. * nornalbion * Omar Vera Ustariz (IBM) * openlifegrid.com +* Oren Hurvitz (Kitely) * otakup0pe * ralphos * RemedyTomm diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index fe1525b..e5b9dcb 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -269,13 +269,15 @@ namespace OpenSim m_console.Commands.AddCommand("region", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-p|--profile=] [--noassets] []", + "save oar [-p|--profile=] [--noassets] [--perm=] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine - + " The OAR path must be a filesystem path." - + " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine - + "--noassets stops assets being saved to the OAR.", + + "--noassets stops assets being saved to the OAR." + Environment.NewLine + + "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine + + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine + + "The OAR path must be a filesystem path." + + " If this is not given then the oar is saved to region.oar in the current directory.", SaveOar); m_console.Commands.AddCommand("region", false, "edit scale", diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 10a83ee..b895afe 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -127,6 +127,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver EntityBase[] entities = m_scene.GetEntities(); List sceneObjects = new List(); + + string checkPermissions = null; + int numObjectsSkippedPermissions = 0; + Object temp; + if (options.TryGetValue("checkPermissions", out temp)) + checkPermissions = (string)temp; // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods @@ -136,9 +142,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (entity is SceneObjectGroup) { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) - sceneObjects.Add((SceneObjectGroup)entity); + { + if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) + { + // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. + ++numObjectsSkippedPermissions; + } + else + { + sceneObjects.Add(sceneObject); + } + } } } @@ -159,7 +175,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver { m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); } - + + if (numObjectsSkippedPermissions > 0) + { + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", + numObjectsSkippedPermissions); + } + // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; @@ -211,6 +234,83 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// + /// Checks whether the user has permission to export an object group to an OAR. + /// + /// The user + /// The object group + /// Which permissions to check: "C" = Copy, "T" = Transfer + /// Whether the user is allowed to export the object to an OAR + private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions) + { + if (checkPermissions == null) + return true; + + IPermissionsModule module = m_scene.RequestModuleInterface(); + if (module == null) + return true; // this shouldn't happen + + // Check whether the user is permitted to export all of the parts in the SOG. If any + // part can't be exported then the entire SOG can't be exported. + + bool permitted = true; + //int primNumber = 1; + + foreach (SceneObjectPart obj in objGroup.Parts) + { + uint perm; + PermissionClass permissionClass = module.GetPermissionClass(user, obj); + switch (permissionClass) + { + case PermissionClass.Owner: + perm = obj.BaseMask; + break; + case PermissionClass.Group: + perm = obj.GroupMask | obj.EveryoneMask; + break; + case PermissionClass.Everyone: + default: + perm = obj.EveryoneMask; + break; + } + + bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; + bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; + + // Special case: if Everyone can copy the object then this implies it can also be + // Transferred. + // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask + // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer + // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. + if (permissionClass != PermissionClass.Owner) + { + canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; + } + + + bool partPermitted = true; + if (checkPermissions.Contains("C") && !canCopy) + partPermitted = false; + if (checkPermissions.Contains("T") && !canTransfer) + partPermitted = false; + + //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); + //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, permitted={8}", + // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, + // permissionClass, checkPermissions, canCopy, canTransfer, permitted); + + if (!partPermitted) + { + permitted = false; + break; + } + + //++primNumber; + } + + return permitted; + } + + /// /// Create the control file for the most up to date archive /// /// diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 08eb80c..f44a3ba 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -128,6 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); + ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); List mainParams = ops.Parse(cmdparams); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index b9bd9a4..3b661ed 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.World.Permissions { - public class PermissionsModule : IRegionModule + public class PermissionsModule : IRegionModule, IPermissionsModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions else m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); + scene.RegisterModuleInterface(this); + //Register functions with Scene External Checks! m_scene.Permissions.OnBypassPermissions += BypassPermissions; m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; @@ -574,46 +576,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (objectOwner != UUID.Zero) objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; - if (m_bypassPermissions) - return objectOwnerMask; - - // Object owners should be able to edit their own content - if (user == objectOwner) - return objectOwnerMask; - - if (IsFriendWithPerms(user, objectOwner)) - { - return objectOwnerMask; - } - // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set - if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) - { - return objectOwnerMask; - } - - // Admin should be able to edit anything in the sim (including admin objects) - if (IsAdministrator(user)) - { - return objectOwnerMask; - } + PermissionClass permissionClass = GetPermissionClass(user, task); - // Users should be able to edit what is over their land. - Vector3 taskPos = task.AbsolutePosition; - ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); - if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod) + switch (permissionClass) { - // Admin objects should not be editable by the above - if (!IsAdministrator(objectOwner)) - { + case PermissionClass.Owner: return objectOwnerMask; - } + case PermissionClass.Group: + return objectGroupMask | objectEveryoneMask; + case PermissionClass.Everyone: + default: + return objectEveryoneMask; } - - // Group permissions - if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) - return objectGroupMask | objectEveryoneMask; - - return objectEveryoneMask; } private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) @@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions return objectFlagsMask; } + public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj) + { + if (obj == null) + return PermissionClass.Everyone; + + if (m_bypassPermissions) + return PermissionClass.Owner; + + // Object owners should be able to edit their own content + UUID objectOwner = obj.OwnerID; + if (user == objectOwner) + return PermissionClass.Owner; + + if (IsFriendWithPerms(user, objectOwner)) + return PermissionClass.Owner; + + // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set + if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) + return PermissionClass.Owner; + + // Admin should be able to edit anything in the sim (including admin objects) + if (IsAdministrator(user)) + return PermissionClass.Owner; + + // Users should be able to edit what is over their land. + Vector3 taskPos = obj.AbsolutePosition; + ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); + if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod) + { + // Admin objects should not be editable by the above + if (!IsAdministrator(objectOwner)) + return PermissionClass.Owner; + } + + // Group permissions + if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0)) + return PermissionClass.Group; + + return PermissionClass.Everyone; + } + /// /// General permissions checks for any operation involving an object. These supplement more specific checks /// implemented by callers. diff --git a/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs new file mode 100644 index 0000000..1ed978b --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs @@ -0,0 +1,54 @@ +/* + * 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 OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.Framework.Interfaces +{ + /// + /// Which set of permissions a user has. + /// + public enum PermissionClass + { + Owner, + Group, + Everyone + }; + + public interface IPermissionsModule + { + + /// + /// Returns the type of permissions that the user has over an object. + /// + /// The user + /// The object + /// The type of permissions the user has over the object + PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj); + } +} -- cgit v1.1 From 44a491f36bbe2094634e356591381c90f87e2125 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 20:31:14 +0100 Subject: uncomment Standalone config in OpenSim.ini.example. This is to make my life easier when creating releases. I think that it also gives a better story for anybody newly compiling from source. --- bin/OpenSim.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c36d2a4..342bce6 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -740,7 +740,7 @@ ;; "config-include/StandaloneCommon.ini.example" to "config-include/StandaloneCommon.ini" before ;; editing it to set the database and backend services that OpenSim will use. ;; - ; Include-Architecture = "config-include/Standalone.ini" + Include-Architecture = "config-include/Standalone.ini" ; Include-Architecture = "config-include/StandaloneHypergrid.ini" ; Include-Architecture = "config-include/Grid.ini" ; Include-Architecture = "config-include/GridHypergrid.ini" -- cgit v1.1 From dab6387bba7a7388e3cdb4ad1eeea646bc03a287 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 21:05:26 +0100 Subject: lock AvatarAppearance.m_attachments when we use it This is partly to address http://opensimulator.org/mantis/view.php?id=5644, though something more thorough is needed. --- OpenSim/Framework/AvatarAppearance.cs | 91 ++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index cce44b0..c69dde3 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -391,10 +391,14 @@ namespace OpenSim.Framework public List GetAttachments() { List alist = new List(); - foreach (KeyValuePair> kvp in m_attachments) + + lock (m_attachments) { - foreach (AvatarAttachment attach in kvp.Value) - alist.Add(new AvatarAttachment(attach)); + foreach (KeyValuePair> kvp in m_attachments) + { + foreach (AvatarAttachment attach in kvp.Value) + alist.Add(new AvatarAttachment(attach)); + } } return alist; @@ -406,10 +410,13 @@ namespace OpenSim.Framework // "[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}", // attach.ItemID, attach.AssetID, attach.AttachPoint); - if (!m_attachments.ContainsKey(attach.AttachPoint)) - m_attachments[attach.AttachPoint] = new List(); - - m_attachments[attach.AttachPoint].Add(attach); + lock (m_attachments) + { + if (!m_attachments.ContainsKey(attach.AttachPoint)) + m_attachments[attach.AttachPoint] = new List(); + + m_attachments[attach.AttachPoint].Add(attach); + } } internal void ReplaceAttachment(AvatarAttachment attach) @@ -418,8 +425,11 @@ namespace OpenSim.Framework // "[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}", // attach.ItemID, attach.AssetID, attach.AttachPoint); - m_attachments[attach.AttachPoint] = new List(); - m_attachments[attach.AttachPoint].Add(attach); + lock (m_attachments) + { + m_attachments[attach.AttachPoint] = new List(); + m_attachments[attach.AttachPoint].Add(attach); + } } /// @@ -448,10 +458,13 @@ namespace OpenSim.Framework if (item == UUID.Zero) { - if (m_attachments.ContainsKey(attachpoint)) + lock (m_attachments) { - m_attachments.Remove(attachpoint); - return true; + if (m_attachments.ContainsKey(attachpoint)) + { + m_attachments.Remove(attachpoint); + return true; + } } return false; @@ -494,11 +507,14 @@ namespace OpenSim.Framework /// Returns null if this item is not attached. public AvatarAttachment GetAttachmentForItem(UUID itemID) { - foreach (KeyValuePair> kvp in m_attachments) + lock (m_attachments) { - int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); - if (index >= 0) - return kvp.Value[index]; + foreach (KeyValuePair> kvp in m_attachments) + { + int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); + if (index >= 0) + return kvp.Value[index]; + } } return null; @@ -506,11 +522,14 @@ namespace OpenSim.Framework public int GetAttachpoint(UUID itemID) { - foreach (KeyValuePair> kvp in m_attachments) + lock (m_attachments) { - int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); - if (index >= 0) - return kvp.Key; + foreach (KeyValuePair> kvp in m_attachments) + { + int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); + if (index >= 0) + return kvp.Key; + } } return 0; @@ -518,27 +537,32 @@ namespace OpenSim.Framework public bool DetachAttachment(UUID itemID) { - foreach (KeyValuePair> kvp in m_attachments) + lock (m_attachments) { - int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); - if (index >= 0) + foreach (KeyValuePair> kvp in m_attachments) { - // Remove it from the list of attachments at that attach point - m_attachments[kvp.Key].RemoveAt(index); - - // And remove the list if there are no more attachments here - if (m_attachments[kvp.Key].Count == 0) - m_attachments.Remove(kvp.Key); - - return true; + int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; }); + if (index >= 0) + { + // Remove it from the list of attachments at that attach point + m_attachments[kvp.Key].RemoveAt(index); + + // And remove the list if there are no more attachments here + if (m_attachments[kvp.Key].Count == 0) + m_attachments.Remove(kvp.Key); + + return true; + } } } + return false; } public void ClearAttachments() { - m_attachments.Clear(); + lock (m_attachments) + m_attachments.Clear(); } #region Packing Functions @@ -576,7 +600,8 @@ namespace OpenSim.Framework data["visualparams"] = visualparams; // Attachments - OSDArray attachs = new OSDArray(m_attachments.Count); + List attachments = GetAttachments(); + OSDArray attachs = new OSDArray(attachments.Count); foreach (AvatarAttachment attach in GetAttachments()) attachs.Add(attach.Pack()); data["attachments"] = attachs; -- cgit v1.1 From ea0f78c97152d3aa54822487e5343ca2db0b47b9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 21:57:22 +0100 Subject: Start locking entire add/remove operations on an IScenePresence.AttachmentsSyncLock object Attach and detach packets are processed asynchronously when received from a viewer. Bugs like http://opensimulator.org/mantis/view.php?id=5644 indicate that in some situations (such as attaching/detaching entire folders of objects at once), there are race conditions between these threads. Since multiple data structures need to be updated on attach/detach, it's not enough to lock the individual collections. Therefore, this commit introduces a new IScenePresence.AttachmentsSyncLock which add/remove operations lock on. --- .../Avatar/Attachments/AttachmentsModule.cs | 382 +++++++++++---------- .../Framework/Interfaces/IAttachmentsModule.cs | 9 + .../Region/Framework/Interfaces/IScenePresence.cs | 8 + OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 + 4 files changed, 228 insertions(+), 175 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 996e2ab..2fa233b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -240,80 +240,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) { -// m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", -// group.Name, group.LocalId, sp.Name, attachmentPt, silent); - - if (sp.GetAttachments(attachmentPt).Contains(group)) - { -// m_log.WarnFormat( -// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", -// group.Name, group.LocalId, sp.Name, AttachmentPt); - - return false; - } - - Vector3 attachPos = group.AbsolutePosition; - - // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should - // be removed when that functionality is implemented in opensim - attachmentPt &= 0x7f; - - // If the attachment point isn't the same as the one previously used - // set it's offset position = 0 so that it appears on the attachment point - // and not in a weird location somewhere unknown. - if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) - { - attachPos = Vector3.Zero; - } - - // AttachmentPt 0 means the client chose to 'wear' the attachment. - if (attachmentPt == 0) - { - // Check object for stored attachment point - attachmentPt = group.AttachmentPoint; - } - - // if we still didn't find a suitable attachment point....... - if (attachmentPt == 0) + lock (sp.AttachmentsSyncLock) { - // Stick it on left hand with Zero Offset from the attachment point. - attachmentPt = (uint)AttachmentPoint.LeftHand; - attachPos = Vector3.Zero; - } - - group.AttachmentPoint = attachmentPt; - group.AbsolutePosition = attachPos; - - // We also don't want to do any of the inventory operations for an NPC. - if (sp.PresenceType != PresenceType.Npc) - { - // Remove any previous attachments - List attachments = sp.GetAttachments(attachmentPt); - - // At the moment we can only deal with a single attachment - if (attachments.Count != 0) + // m_log.DebugFormat( + // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", + // group.Name, group.LocalId, sp.Name, attachmentPt, silent); + + if (sp.GetAttachments(attachmentPt).Contains(group)) { - UUID oldAttachmentItemID = attachments[0].GetFromItemID(); + // m_log.WarnFormat( + // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", + // group.Name, group.LocalId, sp.Name, AttachmentPt); - if (oldAttachmentItemID != UUID.Zero) - DetachSingleAttachmentToInv(oldAttachmentItemID, sp); - else - m_log.WarnFormat( - "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", - attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); + return false; } - - // Add the new attachment to inventory if we don't already have it. - UUID newAttachmentItemID = group.GetFromItemID(); - if (newAttachmentItemID == UUID.Zero) - newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; - ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); + Vector3 attachPos = group.AbsolutePosition; + + // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should + // be removed when that functionality is implemented in opensim + attachmentPt &= 0x7f; + + // If the attachment point isn't the same as the one previously used + // set it's offset position = 0 so that it appears on the attachment point + // and not in a weird location somewhere unknown. + if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) + { + attachPos = Vector3.Zero; + } + + // AttachmentPt 0 means the client chose to 'wear' the attachment. + if (attachmentPt == 0) + { + // Check object for stored attachment point + attachmentPt = group.AttachmentPoint; + } + + // if we still didn't find a suitable attachment point....... + if (attachmentPt == 0) + { + // Stick it on left hand with Zero Offset from the attachment point. + attachmentPt = (uint)AttachmentPoint.LeftHand; + attachPos = Vector3.Zero; + } + + group.AttachmentPoint = attachmentPt; + group.AbsolutePosition = attachPos; + + // We also don't want to do any of the inventory operations for an NPC. + if (sp.PresenceType != PresenceType.Npc) + { + // Remove any previous attachments + List attachments = sp.GetAttachments(attachmentPt); + + // At the moment we can only deal with a single attachment + if (attachments.Count != 0) + { + UUID oldAttachmentItemID = attachments[0].GetFromItemID(); + + if (oldAttachmentItemID != UUID.Zero) + DetachSingleAttachmentToInv(oldAttachmentItemID, sp); + else + m_log.WarnFormat( + "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", + attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); + } + + // Add the new attachment to inventory if we don't already have it. + UUID newAttachmentItemID = group.GetFromItemID(); + if (newAttachmentItemID == UUID.Zero) + newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; + + ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); + } + + AttachToAgent(sp, group, attachmentPt, attachPos, silent); } - AttachToAgent(sp, group, attachmentPt, attachPos, silent); - return true; } @@ -322,14 +325,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) { - foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) + ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); + + if (sp == null) { - RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); + m_log.ErrorFormat( + "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()", + remoteClient.Name, remoteClient.AgentId); + return; + } + + lock (sp.AttachmentsSyncLock) + { + foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) + { + RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt); + } } } - public ISceneEntity RezSingleAttachmentFromInventory( - IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", @@ -344,7 +359,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments remoteClient.Name, remoteClient.AgentId); return null; } - + + return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt); + } + + public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt) + { // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // be removed when that functionality is implemented in opensim AttachmentPt &= 0x7f; @@ -363,65 +383,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) { - SceneObjectGroup objatt; - - if (itemID != UUID.Zero) - objatt = invAccess.RezObject(sp.ControllingClient, - itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, - false, false, sp.UUID, true); - else - objatt = invAccess.RezObject(sp.ControllingClient, - null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, - false, false, sp.UUID, true); - -// m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", -// objatt.Name, remoteClient.Name, AttachmentPt); - - if (objatt != null) + lock (sp.AttachmentsSyncLock) { - // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. - objatt.HasGroupChanged = false; - bool tainted = false; - if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) - tainted = true; - - // This will throw if the attachment fails - try + SceneObjectGroup objatt; + + if (itemID != UUID.Zero) + objatt = invAccess.RezObject(sp.ControllingClient, + itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + false, false, sp.UUID, true); + else + objatt = invAccess.RezObject(sp.ControllingClient, + null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + false, false, sp.UUID, true); + + // m_log.DebugFormat( + // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", + // objatt.Name, remoteClient.Name, AttachmentPt); + + if (objatt != null) { - AttachObject(sp, objatt, attachmentPt, false); + // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. + objatt.HasGroupChanged = false; + bool tainted = false; + if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) + tainted = true; + + // This will throw if the attachment fails + try + { + AttachObject(sp, objatt, attachmentPt, false); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", + objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); + + // Make sure the object doesn't stick around and bail + sp.RemoveAttachment(objatt); + m_scene.DeleteSceneObject(objatt, false); + return null; + } + + if (tainted) + objatt.HasGroupChanged = true; + + // Fire after attach, so we don't get messy perms dialogs + // 4 == AttachedRez + objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); + objatt.ResumeScripts(); + + // Do this last so that event listeners have access to all the effects of the attachment + m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); + + return objatt; } - catch (Exception e) + else { - m_log.ErrorFormat( - "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", - objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); - - // Make sure the object doesn't stick around and bail - sp.RemoveAttachment(objatt); - m_scene.DeleteSceneObject(objatt, false); - return null; + m_log.WarnFormat( + "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", + itemID, sp.Name, attachmentPt); } - - if (tainted) - objatt.HasGroupChanged = true; - - // Fire after attach, so we don't get messy perms dialogs - // 4 == AttachedRez - objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); - objatt.ResumeScripts(); - - // Do this last so that event listeners have access to all the effects of the attachment - m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); } - else - { - m_log.WarnFormat( - "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", - itemID, sp.Name, attachmentPt); - } - - return objatt; } return null; @@ -474,14 +497,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ScenePresence presence; if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) { - // Save avatar attachment information - m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); - - bool changed = presence.Appearance.DetachAttachment(itemID); - if (changed && m_scene.AvatarFactory != null) - m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); + lock (presence.AttachmentsSyncLock) + { + // Save avatar attachment information + m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); - DetachSingleAttachmentToInv(itemID, presence); + bool changed = presence.Appearance.DetachAttachment(itemID); + if (changed && m_scene.AvatarFactory != null) + m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); + + DetachSingleAttachmentToInv(itemID, presence); + } } } @@ -508,24 +534,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ScenePresence presence; if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) { - if (!m_scene.Permissions.CanRezObject( - so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) - return; + lock (presence.AttachmentsSyncLock) + { + if (!m_scene.Permissions.CanRezObject( + so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) + return; - bool changed = presence.Appearance.DetachAttachment(inventoryID); - if (changed && m_scene.AvatarFactory != null) - m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); + bool changed = presence.Appearance.DetachAttachment(inventoryID); + if (changed && m_scene.AvatarFactory != null) + m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); - presence.RemoveAttachment(so); - DetachSceneObjectToGround(so, presence); + presence.RemoveAttachment(so); + DetachSceneObjectToGround(so, presence); - List uuids = new List(); - uuids.Add(inventoryID); - m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); - remoteClient.SendRemoveInventoryItem(inventoryID); - } + List uuids = new List(); + uuids.Add(inventoryID); + m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); + remoteClient.SendRemoveInventoryItem(inventoryID); + } - m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); + m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); + } } /// @@ -567,37 +596,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments EntityBase[] detachEntities = m_scene.GetEntities(); SceneObjectGroup group; - foreach (EntityBase entity in detachEntities) + lock (sp.AttachmentsSyncLock) { - if (entity is SceneObjectGroup) + foreach (EntityBase entity in detachEntities) { - group = (SceneObjectGroup)entity; - if (group.GetFromItemID() == itemID) + if (entity is SceneObjectGroup) { - m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); - sp.RemoveAttachment(group); - - // Prepare sog for storage - group.AttachedAvatar = UUID.Zero; - - group.ForEachPart( - delegate(SceneObjectPart part) - { - // If there are any scripts, - // then always trigger a new object and state persistence in UpdateKnownItem() - if (part.Inventory.ContainsScripts()) - group.HasGroupChanged = true; - } - ); - - group.RootPart.SetParentLocalId(0); - group.IsAttachment = false; - group.AbsolutePosition = group.RootPart.AttachedPos; - - UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID); - m_scene.DeleteSceneObject(group, false); - - return; + group = (SceneObjectGroup)entity; + if (group.GetFromItemID() == itemID) + { + m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); + sp.RemoveAttachment(group); + + // Prepare sog for storage + group.AttachedAvatar = UUID.Zero; + + group.ForEachPart( + delegate(SceneObjectPart part) + { + // If there are any scripts, + // then always trigger a new object and state persistence in UpdateKnownItem() + if (part.Inventory.ContainsScripts()) + group.HasGroupChanged = true; + } + ); + + group.RootPart.SetParentLocalId(0); + group.IsAttachment = false; + group.AbsolutePosition = group.RootPart.AttachedPos; + + UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID); + m_scene.DeleteSceneObject(group, false); + + return; + } } } } @@ -829,4 +861,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return item; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 73d15a5..e6ac6b5 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -88,6 +88,15 @@ namespace OpenSim.Region.Framework.Interfaces ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); /// + /// Rez an attachment from user inventory and change inventory status to match. + /// + /// + /// + /// + /// The scene object that was attached. Null if the scene object could not be found + ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt); + + /// /// Rez multiple attachments from a user's inventory /// /// diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index 8913133..95688ab 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs @@ -61,6 +61,14 @@ namespace OpenSim.Region.Framework.Interfaces AvatarAppearance Appearance { get; set; } /// + /// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments. + /// + /// + /// All add and remove attachment operations must synchronize on this for the lifetime of their operations. + /// + Object AttachmentsSyncLock { get; } + + /// /// The scene objects attached to this avatar. /// /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d65d78d..86e1e11 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -120,6 +120,8 @@ namespace OpenSim.Region.Framework.Scenes /// protected List m_attachments = new List(); + public Object AttachmentsSyncLock { get; private set; } + private Dictionary scriptedcontrols = new Dictionary(); private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; @@ -709,6 +711,8 @@ namespace OpenSim.Region.Framework.Scenes public ScenePresence( IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance, PresenceType type) { + AttachmentsSyncLock = new Object(); + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; m_sceneViewer = new SceneViewer(this); m_animator = new ScenePresenceAnimator(this); -- cgit v1.1 From 294120c9d36f5c6452d5b839ef2543ed4be7af95 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 22:26:04 +0100 Subject: comment out some recent terrain texture logging --- OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | 8 ++++---- OpenSim/Region/Framework/Interfaces/IScenePresence.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 94c1417..c199a77 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -968,10 +968,10 @@ namespace OpenSim.Region.CoreModules.World.Estate args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; - m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); - m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); - m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); - m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); +// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); +// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); +// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); +// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); remoteClient.SendRegionHandshake(Scene.RegionInfo,args); } diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index 95688ab..ff39283 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Interfaces /// All add and remove attachment operations must synchronize on this for the lifetime of their operations. /// Object AttachmentsSyncLock { get; } - + /// /// The scene objects attached to this avatar. /// -- cgit v1.1 From 00f8946bd420a796128e58f025f7f380887306ab Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 22:44:14 +0100 Subject: minor: if the script engine fails to find a prim for a script, also print out that prim's local id in the error message. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 4 ++++ OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 6f963ac..89e6ddb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -418,6 +418,10 @@ namespace OpenSim.Region.Framework.Scenes lock (SceneObjectGroupsByLocalPartID) { +// m_log.DebugFormat( +// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", +// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); + SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in children) SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 55f373e..156fd57 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -594,7 +594,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); if (part == null) { - m_log.Error("[Script] SceneObjectPart unavailable. Script NOT started."); + m_log.ErrorFormat("[Script]: SceneObjectPart with localID {0} unavailable. Script NOT started.", localID); m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n"; m_ScriptFailCount++; return false; -- cgit v1.1 From 56cd7d96851203efa3e84b4c8be70177e2d2d453 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 22:51:56 +0100 Subject: stop the redundant passing in of RegionInfo to SceneGraph, since the Scene is always passed in at the same time. --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 7 ++----- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8 ++++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f86b3b6..e0bc891 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -656,7 +656,7 @@ namespace OpenSim.Region.Framework.Scenes EventManager.OnLandObjectRemoved += new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); - m_sceneGraph = new SceneGraph(this, m_regInfo); + m_sceneGraph = new SceneGraph(this); // If the scene graph has an Unrecoverable error, restart this sim. // Currently the only thing that causes it to happen is two kinds of specific diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 89e6ddb..40dc2f8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -74,7 +74,6 @@ namespace OpenSim.Region.Framework.Scenes protected internal EntityManager Entities = new EntityManager(); - protected RegionInfo m_regInfo; protected Scene m_parentScene; protected Dictionary m_updateList = new Dictionary(); protected int m_numRootAgents = 0; @@ -108,10 +107,9 @@ namespace OpenSim.Region.Framework.Scenes #endregion - protected internal SceneGraph(Scene parent, RegionInfo regInfo) + protected internal SceneGraph(Scene parent) { m_parentScene = parent; - m_regInfo = regInfo; } public PhysicsScene PhysicsScene @@ -122,7 +120,6 @@ namespace OpenSim.Region.Framework.Scenes // If we're not doing the initial set // Then we've got to remove the previous // event handler - if (_PhyScene != null) _PhyScene.OnPhysicsCrash -= physicsBasedCrash; @@ -593,7 +590,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence newAvatar = null; // ScenePresence always defaults to child agent - newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance, type); + newAvatar = new ScenePresence(client, m_parentScene, appearance, type); AddScenePresence(newAvatar); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 86e1e11..9b8afe3 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -707,9 +707,9 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region Constructor(s) - + public ScenePresence( - IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance, PresenceType type) + IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) { AttachmentsSyncLock = new Object(); @@ -718,14 +718,14 @@ namespace OpenSim.Region.Framework.Scenes m_animator = new ScenePresenceAnimator(this); PresenceType = type; m_DrawDistance = world.DefaultDrawDistance; - m_rootRegionHandle = reginfo.RegionHandle; + m_rootRegionHandle = world.RegionInfo.RegionHandle; m_controllingClient = client; m_firstname = m_controllingClient.FirstName; m_lastname = m_controllingClient.LastName; m_name = String.Format("{0} {1}", m_firstname, m_lastname); m_scene = world; m_uuid = client.AgentId; - m_regionInfo = reginfo; + m_regionInfo = world.RegionInfo; m_localId = m_scene.AllocateLocalId(); UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); -- cgit v1.1 From 62b24505295a49b3b3ba61a1a840d0fa5825340f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 22:54:54 +0100 Subject: remove the unused SP.initializeScenePresence() --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 25 ++---------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9b8afe3..1050507 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3568,29 +3568,6 @@ namespace OpenSim.Region.Framework.Scenes } } - - public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene) - { - m_controllingClient = client; - m_regionInfo = region; - m_scene = scene; - - RegisterToEvents(); - - /* - AbsolutePosition = client.StartPos; - - Animations = new AvatarAnimations(); - Animations.LoadAnims(); - - m_animations = new List(); - m_animations.Add(Animations.AnimsUUID["STAND"]); - m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber); - - SetDirectionVectors(); - */ - } - internal void PushForce(Vector3 impulse) { if (PhysicsActor != null) @@ -3618,6 +3595,7 @@ namespace OpenSim.Region.Framework.Scenes obj.ignoreControls = (ScriptControlled)controls; obj.eventControls = (ScriptControlled)controls; } + if (pass_on == 1 && accept == 1) { IgnoredControls = ScriptControlled.CONTROL_ZERO; @@ -3638,6 +3616,7 @@ namespace OpenSim.Region.Framework.Scenes scriptedcontrols[Script_item_UUID] = obj; } } + ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); } -- cgit v1.1 From dea0935361d536da7fada83069e06a7c476b5351 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 12 Sep 2011 23:00:15 +0100 Subject: eliminate redundant SP.m_regionInfo since it always has the scene. We were already referencing through the scene in some places. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1050507..879352d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -188,7 +188,6 @@ namespace OpenSim.Region.Framework.Scenes private float m_health = 100f; - protected RegionInfo m_regionInfo; protected ulong crossingFromRegion; private readonly Vector3[] Dir_Vectors = new Vector3[9]; @@ -725,7 +724,6 @@ namespace OpenSim.Region.Framework.Scenes m_name = String.Format("{0} {1}", m_firstname, m_lastname); m_scene = world; m_uuid = client.AgentId; - m_regionInfo = world.RegionInfo; m_localId = m_scene.AllocateLocalId(); UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); @@ -1156,7 +1154,7 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat("Completed movement"); - m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); + m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); SendInitialData(); // Create child agents in neighbouring regions @@ -2877,8 +2875,8 @@ namespace OpenSim.Region.Framework.Scenes /// protected int HaveNeighbor(Cardinals car, ref int[] fix) { - uint neighbourx = m_regionInfo.RegionLocX; - uint neighboury = m_regionInfo.RegionLocY; + uint neighbourx = m_scene.RegionInfo.RegionLocX; + uint neighboury = m_scene.RegionInfo.RegionLocY; int dir = (int)car; @@ -2898,8 +2896,8 @@ namespace OpenSim.Region.Framework.Scenes if (neighbourRegion == null) { - fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); - fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); + fix[0] = (int)(m_scene.RegionInfo.RegionLocX - neighbourx); + fix[1] = (int)(m_scene.RegionInfo.RegionLocY - neighboury); return dir * (-1); } else @@ -3616,7 +3614,7 @@ namespace OpenSim.Region.Framework.Scenes scriptedcontrols[Script_item_UUID] = obj; } } - + ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); } -- cgit v1.1 From 306af9934aac2aaf7fe9baa156b3cc57ff3f3f56 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 17:13:42 +0100 Subject: In an object return message, send a null-terminated empty string in binary bucket to prevent a viewer 3 crash. This is the message sent to the client when the object is returned. We were sending byte[0] in the binary bucket. This didn't kill viewer 1 but did terminate viewer 3 (don't know about viewer 2). So sending "\0" instead. This is to address http://opensimulator.org/mantis/view.php?id=5683 --- OpenSim/Framework/Util.cs | 42 ++++++++++++++++++++++++++++++-- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 745da17..c4fc643 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1372,11 +1372,30 @@ namespace OpenSim.Framework return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; } + /// + /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary. + /// + /// + /// If null or empty, then an bytes[0] is returned. + /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] + /// + /// + /// Arguments to substitute into the string via the {} mechanism. + /// + /// public static byte[] StringToBytes256(string str, params object[] args) { return StringToBytes256(string.Format(str, args)); } - + + /// + /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary. + /// + /// + /// If null or empty, then an bytes[0] is returned. + /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] + /// + /// public static byte[] StringToBytes256(string str) { if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } @@ -1395,11 +1414,30 @@ namespace OpenSim.Framework return data; } + /// + /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary. + /// + /// + /// If null or empty, then an bytes[0] is returned. + /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] + /// + /// + /// Arguments to substitute into the string via the {} mechanism. + /// + /// public static byte[] StringToBytes1024(string str, params object[] args) { return StringToBytes1024(string.Format(str, args)); } - + + /// + /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary. + /// + /// + /// If null or empty, then an bytes[0] is returned. + /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0] + /// + /// public static byte[] StringToBytes1024(string str) { if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e0bc891..a0a2624 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1579,7 +1579,9 @@ namespace OpenSim.Region.Framework.Scenes msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; msg.Position = Vector3.Zero; msg.RegionID = RegionInfo.RegionID.Guid; - msg.binaryBucket = new byte[0]; + + // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. + msg.binaryBucket = Util.StringToBytes256("\0"); if (ret.Value.count > 1) msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); else -- cgit v1.1 From 88bd71b9786f5af9ce185fa1c885622f41712371 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 17:40:39 +0100 Subject: improve TestAddSceneObject() to test a multi-part object rather than a single-part --- .../Scenes/Tests/SceneObjectBasicTests.cs | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 1ea2329..8f2e21f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -52,22 +52,25 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestHelpers.InMethod(); Scene scene = SceneHelpers.SetupScene(); + int partsToTestCount = 3; - string objName = "obj1"; - UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); - - SceneObjectPart part - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = objName, UUID = objUuid }; + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); + SceneObjectPart[] parts = so.Parts; - Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part), false), Is.True); - - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid); + Assert.That(scene.AddNewSceneObject(so, false), Is.True); + SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID); + SceneObjectPart[] retrievedParts = retrievedSo.Parts; //m_log.Debug("retrievedPart : {0}", retrievedPart); // If the parts have the same UUID then we will consider them as one and the same - Assert.That(retrievedPart.Name, Is.EqualTo(objName)); - Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); + Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount)); + + for (int i = 0; i < partsToTestCount; i++) + { + Assert.That(retrievedParts[i].Name, Is.EqualTo(parts[i].Name)); + Assert.That(retrievedParts[i].UUID, Is.EqualTo(parts[i].UUID)); + } } [Test] -- cgit v1.1 From c14f0a22d44c582fb277ba34dec7cee629ba7f4a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 17:52:10 +0100 Subject: Add new TestGetSceneObjectByPartLocalId() for retrieving a scene object via the local id of one of its parts --- .../Scenes/Tests/SceneObjectBasicTests.cs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 8f2e21f..281b85c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -106,6 +106,33 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name)); Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); } + + /// + /// Test retrieving a scene object via the local id of one of its parts. + /// + [Test] + public void TestGetSceneObjectByPartLocalId() + { + TestHelpers.InMethod(); + + Scene scene = SceneHelpers.SetupScene(); + int partsToTestCount = 3; + + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); + SceneObjectPart[] parts = so.Parts; + + scene.AddNewSceneObject(so, false); + + // Test getting via the root part's local id + Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Not.Null); + + // Test getting via a non root part's local id + Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Not.Null); + + // Test that we don't get back an object for a local id that doesn't exist + Assert.That(scene.GetGroupByPrim(999), Is.Null); + } /// /// Test deleting an object from a scene. -- cgit v1.1 From 07ba28f1dece06309cfbf7f487b7a779e49033bb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 17:56:02 +0100 Subject: In SG.AddSceneObject(), stop unnecessarily adding the root part to object indexes sepearately from the other parts. The SOG.Parts property contains the root part as well as the non-root parts --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 40dc2f8..4d7bc0c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -369,12 +369,12 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); - SceneObjectPart[] children = sceneObject.Parts; + SceneObjectPart[] parts = sceneObject.Parts; // Clamp child prim sizes and add child prims to the m_numPrim count if (m_parentScene.m_clampPrimSize) { - foreach (SceneObjectPart part in children) + foreach (SceneObjectPart part in parts) { Vector3 scale = part.Shape.Scale; @@ -388,7 +388,7 @@ namespace OpenSim.Region.Framework.Scenes part.Shape.Scale = scale; } } - m_numPrim += children.Length; + m_numPrim += parts.Length; sceneObject.AttachToScene(m_parentScene); @@ -408,8 +408,7 @@ namespace OpenSim.Region.Framework.Scenes lock (SceneObjectGroupsByFullPartID) { - SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject; - foreach (SceneObjectPart part in children) + foreach (SceneObjectPart part in parts) SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; } @@ -419,8 +418,7 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); - SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject; - foreach (SceneObjectPart part in children) + foreach (SceneObjectPart part in parts) SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; } -- cgit v1.1 From f09a90d8a7cf1e4b32845c3ffddbf1ca780e664c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 18:08:05 +0100 Subject: extend TestGetSceneObjectByPartLocalId() to test state after scene object deletion --- OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 281b85c..9586877 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -132,6 +132,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Test that we don't get back an object for a local id that doesn't exist Assert.That(scene.GetGroupByPrim(999), Is.Null); + + // Now delete the scene object and check again + scene.DeleteSceneObject(so, false); + + Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Null); + Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Null); } /// -- cgit v1.1 From df73833a2c79a1a60536e386b5884581d9f2f4b3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 18:11:13 +0100 Subject: stop the duplicate remove of the root part ids from the full part and local part indexes in SG.DeleteSceneObject() this is unnecessary because the parts array iterated through contains the root part as well as the non-root parts --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 -- OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 4d7bc0c..46c22ca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -459,7 +459,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = grp.Parts; for (int i = 0; i < parts.Length; i++) SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); - SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID); } lock (SceneObjectGroupsByLocalPartID) @@ -467,7 +466,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = grp.Parts; for (int i = 0; i < parts.Length; i++) SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); - SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId); } return Entities.Remove(uuid); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 9586877..80f198d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -135,7 +135,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Now delete the scene object and check again scene.DeleteSceneObject(so, false); - + Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Null); Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Null); } -- cgit v1.1 From 618277e797c7d501f98e884e50abd313498cf00b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 20:25:32 +0100 Subject: Comment out attachments code in Scene.IncomingCreateObject(UUID userID, UUID itemID) for now As far as I can see, this is only invoked by a PUT request to ObjectHandlers, which is not being used anyway. Invoking attachments code at this point is probably inappropriate since it would still be invoked when the client entered the scene. Being commented to simplify analysis of attachments issues. Can be uncommented when in use. Also, small tweak to lock and log removal of a SOG from the SceneObjectGroupsByLocalPartID collection in SceneGraph.GetGroupByPrim() if an inconsistency is found. --- .../Avatar/Attachments/AttachmentsModule.cs | 17 ++++++++++++--- OpenSim/Region/Framework/Scenes/Scene.cs | 18 +++++++++------- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 25 ++++++++++++++++++++-- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2fa233b..c817559 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -143,6 +143,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void SaveChangedAttachments(IScenePresence sp) { +// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); + foreach (SceneObjectGroup grp in sp.GetAttachments()) { if (grp.HasGroupChanged) // Resizer scripts? @@ -242,9 +244,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { lock (sp.AttachmentsSyncLock) { - // m_log.DebugFormat( - // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", - // group.Name, group.LocalId, sp.Name, attachmentPt, silent); +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", +// group.Name, group.LocalId, sp.Name, attachmentPt, silent); if (sp.GetAttachments(attachmentPt).Contains(group)) { @@ -365,6 +367,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt) { +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", +// (AttachmentPoint)AttachmentPt, itemID, sp.Name); + // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // be removed when that functionality is implemented in opensim AttachmentPt &= 0x7f; @@ -485,6 +491,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachObject(uint objectLocalID, IClientAPI remoteClient) { +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name); + SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); if (group != null) { @@ -588,6 +597,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) { +// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); + if (itemID == UUID.Zero) // If this happened, someone made a mistake.... return; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a0a2624..c5c9260 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2461,14 +2461,16 @@ namespace OpenSim.Region.Framework.Scenes /// False public virtual bool IncomingCreateObject(UUID userID, UUID itemID) { - //m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID); - - ScenePresence sp = GetScenePresence(userID); - if (sp != null && AttachmentsModule != null) - { - uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); - AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt); - } + m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID); + + // Commented out since this is as yet unused and is arguably not the appropriate place to do this, as + // attachments are being rezzed elsewhere in AddNewClient() +// ScenePresence sp = GetScenePresence(userID); +// if (sp != null && AttachmentsModule != null) +// { +// uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); +// AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt); +// } return false; } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 46c22ca..f03cf7b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -431,6 +431,10 @@ namespace OpenSim.Region.Framework.Scenes /// true if the object was deleted, false if there was no object to delete public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) { +// m_log.DebugFormat( +// "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}", +// uuid, resultOfObjectLinked); + EntityBase entity; if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup))) return false; @@ -878,7 +882,8 @@ namespace OpenSim.Region.Framework.Scenes if (Entities.TryGetValue(localID, out entity)) return entity as SceneObjectGroup; - //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); +// m_log.DebugFormat("[SCENE GRAPH]: Entered GetGroupByPrim with localID {0}", localID); + SceneObjectGroup sog; lock (SceneObjectGroupsByLocalPartID) SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog); @@ -886,8 +891,24 @@ namespace OpenSim.Region.Framework.Scenes if (sog != null) { if (sog.HasChildPrim(localID)) + { +// m_log.DebugFormat( +// "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.", +// sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); + return sog; - SceneObjectGroupsByLocalPartID.Remove(localID); + } + else + { + lock (SceneObjectGroupsByLocalPartID) + { + m_log.WarnFormat( + "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", + sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); + + SceneObjectGroupsByLocalPartID.Remove(localID); + } + } } EntityBase[] entityList = GetEntities(); -- cgit v1.1 From 8880aea728af2ccb95ea2400c7d180aa4dc98112 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 22:13:58 +0100 Subject: Stop attempts to rewear already worn items from removing and reattaching. Viewer 2/3 will sometimes attempt to rewear attachments, even though they have already been attached during the main login process. This change ignores those attempts. This stops script failures during login, as the rewearing was racing with the script startup code. It might also help with attachments being abnormally put into deleted state. Hopefully resolves some more of http://opensimulator.org/mantis/view.php?id=5644 --- .../Avatar/Attachments/AttachmentsModule.cs | 119 +++++++++++++-------- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 4 +- .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 13 +++ .../Framework/Scenes/SceneObjectPartInventory.cs | 5 + 4 files changed, 97 insertions(+), 44 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index c817559..1e9a001 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -147,18 +147,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments foreach (SceneObjectGroup grp in sp.GetAttachments()) { - if (grp.HasGroupChanged) // Resizer scripts? - { +// if (grp.HasGroupChanged) // Resizer scripts? +// { grp.IsAttachment = false; grp.AbsolutePosition = grp.RootPart.AttachedPos; UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); grp.IsAttachment = true; - } +// } } } public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) { +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", +// m_scene.RegionInfo.RegionName, sp.Name, silent); + foreach (SceneObjectGroup sop in sp.GetAttachments()) { sop.Scene.DeleteSceneObject(sop, silent); @@ -214,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); // Save avatar attachment information - m_log.Info( + m_log.Debug( "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", AttachmentPoint: " + AttachmentPt); @@ -339,6 +343,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments lock (sp.AttachmentsSyncLock) { +// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); + foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) { RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt); @@ -349,7 +355,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { // m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", +// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); @@ -375,6 +381,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // be removed when that functionality is implemented in opensim AttachmentPt &= 0x7f; + // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). + // This often happens during login - not sure the exact reason. + // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the + // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login + // before anything has actually been attached. + bool alreadyOn = false; + List existingAttachments = sp.GetAttachments(); + foreach (SceneObjectGroup so in existingAttachments) + { + if (so.GetFromItemID() == itemID) + { + alreadyOn = true; + break; + } + } + +// if (sp.Appearance.GetAttachmentForItem(itemID) != null) + if (alreadyOn) + { +// m_log.WarnFormat( +// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", +// sp.Name, itemID, AttachmentPt); + + return null; + } + SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); if (att == null) @@ -467,8 +499,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) { // m_log.DebugFormat( -// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", -// att.Name, remoteClient.Name, AttachmentPt, itemID); +// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", +// att.Name, sp.Name, AttachmentPt, itemID); if (UUID.Zero == itemID) { @@ -524,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", -// remoteClient.Name, sceneObjectID); +// remoteClient.Name, soLocalId); SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); @@ -677,45 +709,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { if (grp != null) { - if (!grp.HasGroupChanged) + if (grp.HasGroupChanged || grp.ContainsScripts()) { m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", + "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", grp.UUID, grp.AttachmentPoint); - return; - } + string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); - m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", - grp.UUID, grp.AttachmentPoint); + InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); + item = m_scene.InventoryService.GetItem(item); - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); - - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = m_scene.InventoryService.GetItem(item); - - if (item != null) + if (item != null) + { + AssetBase asset = m_scene.CreateAsset( + grp.GetPartName(grp.LocalId), + grp.GetPartDescription(grp.LocalId), + (sbyte)AssetType.Object, + Utils.StringToBytes(sceneObjectXml), + remoteClient.AgentId); + m_scene.AssetService.Store(asset); + + item.AssetID = asset.FullID; + item.Description = asset.Description; + item.Name = asset.Name; + item.AssetType = asset.Type; + item.InvType = (int)InventoryType.Object; + + m_scene.InventoryService.UpdateItem(item); + + // this gets called when the agent logs off! + if (remoteClient != null) + remoteClient.SendInventoryItemCreateUpdate(item, 0); + } + } + else { - AssetBase asset = m_scene.CreateAsset( - grp.GetPartName(grp.LocalId), - grp.GetPartDescription(grp.LocalId), - (sbyte)AssetType.Object, - Utils.StringToBytes(sceneObjectXml), - remoteClient.AgentId); - m_scene.AssetService.Store(asset); - - item.AssetID = asset.FullID; - item.Description = asset.Description; - item.Name = asset.Name; - item.AssetType = asset.Type; - item.InvType = (int)InventoryType.Object; - - m_scene.InventoryService.UpdateItem(item); - - // this gets called when the agent logs off! - if (remoteClient != null) - remoteClient.SendInventoryItemCreateUpdate(item, 0); + m_log.DebugFormat( + "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", + grp.UUID, grp.AttachmentPoint); } } } @@ -735,7 +767,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments private void AttachToAgent( IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) { -// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); so.DetachFromBackup(); @@ -788,7 +821,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// The user inventory item created that holds the attachment. private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) { -// m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", +// grp.Name, grp.LocalId, remoteClient.Name); Vector3 inventoryStoredPosition = new Vector3 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f03cf7b..36c5c52 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -652,7 +652,7 @@ namespace OpenSim.Region.Framework.Scenes if (!Entities.Remove(agentID)) { m_log.WarnFormat( - "[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", + "[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", agentID); } @@ -675,7 +675,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); + m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 4bca3d0..905ecc9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -389,5 +389,18 @@ namespace OpenSim.Region.Framework.Scenes for (int i = 0; i < parts.Length; i++) parts[i].Inventory.ResumeScripts(); } + + /// + /// Returns true if any part in the scene object contains scripts, false otherwise. + /// + /// + public bool ContainsScripts() + { + foreach (SceneObjectPart part in Parts) + if (part.Inventory.ContainsScripts()) + return true; + + return false; + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index e40e57d..57adda7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1035,10 +1035,15 @@ namespace OpenSim.Region.Framework.Scenes item.BasePermissions = perms; } } + m_inventorySerial++; HasInventoryChanged = true; } + /// + /// Returns true if this part inventory contains any scripts. False otherwise. + /// + /// public bool ContainsScripts() { lock (m_items) -- cgit v1.1 From 62b3e74bc5c3f08f33e15b30d04a799db4228c06 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 22:24:33 +0100 Subject: minor: remove redundant grp != null check from AM.UpdateKnownItem() --- .../Avatar/Attachments/AttachmentsModule.cs | 69 +++++++++++----------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 1e9a001..ae19224 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -707,49 +707,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) { - if (grp != null) + if (grp.HasGroupChanged || grp.ContainsScripts()) { - if (grp.HasGroupChanged || grp.ContainsScripts()) - { - m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", - grp.UUID, grp.AttachmentPoint); + m_log.DebugFormat( + "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", + grp.UUID, grp.AttachmentPoint); - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); + string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = m_scene.InventoryService.GetItem(item); + InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); + item = m_scene.InventoryService.GetItem(item); - if (item != null) - { - AssetBase asset = m_scene.CreateAsset( - grp.GetPartName(grp.LocalId), - grp.GetPartDescription(grp.LocalId), - (sbyte)AssetType.Object, - Utils.StringToBytes(sceneObjectXml), - remoteClient.AgentId); - m_scene.AssetService.Store(asset); - - item.AssetID = asset.FullID; - item.Description = asset.Description; - item.Name = asset.Name; - item.AssetType = asset.Type; - item.InvType = (int)InventoryType.Object; - - m_scene.InventoryService.UpdateItem(item); - - // this gets called when the agent logs off! - if (remoteClient != null) - remoteClient.SendInventoryItemCreateUpdate(item, 0); - } - } - else + if (item != null) { - m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", - grp.UUID, grp.AttachmentPoint); + AssetBase asset = m_scene.CreateAsset( + grp.GetPartName(grp.LocalId), + grp.GetPartDescription(grp.LocalId), + (sbyte)AssetType.Object, + Utils.StringToBytes(sceneObjectXml), + remoteClient.AgentId); + m_scene.AssetService.Store(asset); + + item.AssetID = asset.FullID; + item.Description = asset.Description; + item.Name = asset.Name; + item.AssetType = asset.Type; + item.InvType = (int)InventoryType.Object; + + m_scene.InventoryService.UpdateItem(item); + + // this gets called when the agent logs off! + if (remoteClient != null) + remoteClient.SendInventoryItemCreateUpdate(item, 0); } } + else + { + m_log.DebugFormat( + "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", + grp.UUID, grp.AttachmentPoint); + } } /// -- cgit v1.1 From 2d62484f11710cbeb066ab6bf02f78ad379ecca3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 22:27:33 +0100 Subject: Remove UpdateKnownItem() from IAttachmentsModule. It's not appropriate for code outside the attachments module to call this. --- .../Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 2 +- OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index ae19224..03837b5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -705,7 +705,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// - public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) + private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) { if (grp.HasGroupChanged || grp.ContainsScripts()) { diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index e6ac6b5..5ffbec8 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -138,14 +138,5 @@ namespace OpenSim.Region.Framework.Interfaces /// /// void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos); - - /// - /// Update the user inventory with a changed attachment - /// - /// - /// - /// - /// - void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID); } } -- cgit v1.1 From 61affee814b6c2a09cb33b1823f009d386f54818 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 22:33:15 +0100 Subject: remove redunant itemID and agentID arguments from UpdateKnownItem(). itemID is always taken taken from the group's stored item id, and agentID is never used. --- .../Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 03837b5..b9cd880 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -151,7 +151,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // { grp.IsAttachment = false; grp.AbsolutePosition = grp.RootPart.AttachedPos; - UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); + UpdateKnownItem(sp.ControllingClient, grp); grp.IsAttachment = true; // } } @@ -668,7 +668,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.IsAttachment = false; group.AbsolutePosition = group.RootPart.AttachedPos; - UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID); + UpdateKnownItem(sp.ControllingClient, group); m_scene.DeleteSceneObject(group, false); return; @@ -703,9 +703,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// - /// - /// - private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) + private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp) { if (grp.HasGroupChanged || grp.ContainsScripts()) { @@ -715,7 +713,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); + InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); if (item != null) -- cgit v1.1 From 1084d8f6a2bcf63c594e1a8bd180c42f51b05e2f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 22:39:06 +0100 Subject: Remove code from DetachSingleAttachmentToInv() that sets group changed on all parts, now that we're performing this check in UpdateKnownItem() for other purposes --- .../CoreModules/Avatar/Attachments/AttachmentsModule.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index b9cd880..b965d75 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -653,17 +653,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Prepare sog for storage group.AttachedAvatar = UUID.Zero; - - group.ForEachPart( - delegate(SceneObjectPart part) - { - // If there are any scripts, - // then always trigger a new object and state persistence in UpdateKnownItem() - if (part.Inventory.ContainsScripts()) - group.HasGroupChanged = true; - } - ); - group.RootPart.SetParentLocalId(0); group.IsAttachment = false; group.AbsolutePosition = group.RootPart.AttachedPos; -- cgit v1.1 From bd991fc95f8ec648f7dbb0086ae716e4204d1687 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Sep 2011 22:54:50 +0100 Subject: Don't try and delete attachments for child agent close --- .../Attachments/Tests/AttachmentsModuleTests.cs | 32 ++++++++++++++++++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 35183b3..ff3358f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -220,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); } + /// + /// Test that attachments don't hang about in the scene when the agent is closed + /// + [Test] + public void TestRemoveAttachmentsOnAvatarExit() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID userId = TestHelpers.ParseTail(0x1); + UUID attItemId = TestHelpers.ParseTail(0x2); + UUID attAssetId = TestHelpers.ParseTail(0x3); + string attName = "att"; + + UserAccountHelpers.CreateUserWithInventory(scene, userId); + InventoryItemBase attItem + = UserInventoryHelpers.CreateInventoryItem( + scene, attName, attItemId, attAssetId, userId, InventoryType.Object); + + AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); + acd.Appearance = new AvatarAppearance(); + acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); + ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); + + SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; + + scene.IncomingCloseAgent(presence.UUID); + + // Check that we can't retrieve this attachment from the scene. + Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); + } + [Test] public void TestRezAttachmentsOnAvatarEntrance() { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 879352d..a8eff70 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3404,7 +3404,8 @@ namespace OpenSim.Region.Framework.Scenes public void Close() { - m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false); + if (!IsChildAgent) + m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false); lock (m_knownChildRegions) { -- cgit v1.1 From 42f1b88eb2492f8d218526c1b30ac027a65d67f3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Sep 2011 18:13:36 +0100 Subject: If a prim inventory becomes empty through deletion, send an empty xfer file name rather than one that references a metadata file containing only the folder object. If we do this, then viewer 3 crashes when we try and rez a script directly in an attachment's prim inventory. Sending an empty file name was already being done if the prim's inventory had never been touched. Now we always do that if there are no items in that inventory. Hopefully addresses the remaining point in http://opensimulator.org/mantis/view.php?id=5644 --- .../Framework/Scenes/SceneObjectPartInventory.cs | 63 +++++++++++++++------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 57adda7..59ac30d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -784,6 +784,10 @@ namespace OpenSim.Region.Framework.Scenes private bool CreateInventoryFile() { +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", +// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial); + if (m_inventoryFileName == String.Empty || m_inventoryFileNameSerial < m_inventorySerial) { @@ -797,6 +801,10 @@ namespace OpenSim.Region.Framework.Scenes { foreach (TaskInventoryItem item in m_items.Values) { +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", +// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId); + UUID ownerID = item.OwnerID; uint everyoneMask = 0; uint baseMask = item.BasePermissions; @@ -856,28 +864,43 @@ namespace OpenSim.Region.Framework.Scenes /// public void RequestInventoryFile(IClientAPI client, IXfer xferManager) { - CreateInventoryFile(); - - if (m_inventorySerial == 0) // No inventory + lock (m_items) { - client.SendTaskInventory(m_part.UUID, 0, new byte[0]); - return; - } - - // In principle, we should only do the rest if the inventory changed; - // by sending m_inventorySerial to the client, it ought to know - // that nothing changed and that it doesn't need to request the file. - // Unfortunately, it doesn't look like the client optimizes this; - // the client seems to always come back and request the Xfer, - // no matter what value m_inventorySerial has. + CreateInventoryFile(); - if (m_inventoryFileData.Length > 2) - // Add the file for Xfer - xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); - - // Tell the client we're ready to Xfer the file - client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, - Util.StringToBytes256(m_inventoryFileName)); + // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing + // a new script if any previous deletion has left the prim inventory empty. + if (m_items.Count == 0) // No inventory + { +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items", +// m_part.Name, m_part.LocalId, m_part.UUID, client.Name); + + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); + return; + } + + // In principle, we should only do the rest if the inventory changed; + // by sending m_inventorySerial to the client, it ought to know + // that nothing changed and that it doesn't need to request the file. + // Unfortunately, it doesn't look like the client optimizes this; + // the client seems to always come back and request the Xfer, + // no matter what value m_inventorySerial has. + // FIXME: Could probably be > 0 here rather than > 2 + if (m_inventoryFileData.Length > 2) + { + // Add the file for Xfer + // m_log.DebugFormat( + // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", + // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); + + xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); + } + + // Tell the client we're ready to Xfer the file + client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, + Util.StringToBytes256(m_inventoryFileName)); + } } /// -- cgit v1.1 From 8fb3e71b14e28bf8a4ddb72e3d1b529128f090ce Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Sep 2011 18:36:22 +0100 Subject: Shuffle order of code in invnetory connector GetFolderContent() calls to avoid a possible race condition --- .../Inventory/LocalInventoryServiceConnector.cs | 15 +++++++++------ .../Inventory/RemoteXInventoryServiceConnector.cs | 15 +++++++++------ .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index 1c83f8e..097ff1a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -185,15 +185,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); - Util.FireAndForget(delegate + + if (UserManager != null) { - if (UserManager != null) + // Protect ourselves against the caller subsequently modifying the items list + List items = new List(invCol.Items); + + Util.FireAndForget(delegate { - // Protect ourselves against the caller subsequently modifying the items list - foreach (InventoryItemBase item in new List(invCol.Items)) + foreach (InventoryItemBase item in items) UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); - } - }); + }); + } return invCol; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index c9c716c..73ab4e3 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -193,15 +193,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); - Util.FireAndForget(delegate + + if (UserManager != null) { - if (UserManager != null) + // Protect ourselves against the caller subsequently modifying the items list + List items = new List(invCol.Items); + + Util.FireAndForget(delegate { - // Protect ourselves against the caller subsequently modifying the items list - foreach (InventoryItemBase item in new List(invCol.Items)) + foreach (InventoryItemBase item in items) UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); - } - }); + }); + } return invCol; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 59ac30d..6085f1e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -875,7 +875,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items", // m_part.Name, m_part.LocalId, m_part.UUID, client.Name); - + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); return; } -- cgit v1.1 From a4cc5f628f053ad1f9f849addf79551cd58e9337 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Sep 2011 18:42:10 +0100 Subject: Only bother to create an inventory xfer file if there are any items in a prim inventory --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 6085f1e..d63b411 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -866,8 +866,6 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_items) { - CreateInventoryFile(); - // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing // a new script if any previous deletion has left the prim inventory empty. if (m_items.Count == 0) // No inventory @@ -879,6 +877,8 @@ namespace OpenSim.Region.Framework.Scenes client.SendTaskInventory(m_part.UUID, 0, new byte[0]); return; } + + CreateInventoryFile(); // In principle, we should only do the rest if the inventory changed; // by sending m_inventorySerial to the client, it ought to know -- cgit v1.1 From de19dc3024e5359f594d0a32c593d905163c24ea Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Sep 2011 18:58:58 +0100 Subject: refactor: rename SOG/SOP.GetProperties() to SendPropertiesToClient() to reflect what it actually does This also makes it consistent with some other methods that send data to the client. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +-- .../World/Objects/BuySell/BuySellModule.cs | 4 +-- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 18 ++++++------ .../Framework/Scenes/Scene.PacketHandlers.cs | 4 +-- .../Region/Framework/Scenes/SceneObjectGroup.cs | 20 ++++++-------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 32 ++++++++++++---------- .../Framework/Scenes/SceneObjectPartInventory.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 2 +- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e9ee7be..b5c6742 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4119,8 +4119,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP while (updatesThisCall < m_maxUpdates) { lock (m_entityProps.SyncRoot) - if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) - break; + if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) + break; ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; if (update.SendFamilyProps) diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs index 8b78701..1e4f0a4 100644 --- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs @@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell part.ParentGroup.HasGroupChanged = true; - part.GetProperties(client); + part.SendPropertiesToClient(client); } public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice) @@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell part.SalePrice = 10; group.HasGroupChanged = true; - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); part.TriggerScriptChangedEvent(Changed.OWNER); group.ResumeScripts(); part.ScheduleFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 9dcd10a..f9dba2d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -274,7 +274,7 @@ namespace OpenSim.Region.Framework.Scenes if (group.UpdateInventoryItem(item)) remoteClient.SendAgentAlertMessage("Script saved", false); - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); // Trigger rerunning of script (use TriggerRezScript event, see RezScript) ArrayList errors = new ArrayList(); @@ -999,7 +999,7 @@ namespace OpenSim.Region.Framework.Scenes } group.RemoveInventoryItem(localID, itemID); - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); } private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) @@ -1272,7 +1272,7 @@ namespace OpenSim.Region.Framework.Scenes if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar)) { - destPart.GetProperties(avatar.ControllingClient); + destPart.SendPropertiesToClient(avatar.ControllingClient); } } @@ -1427,7 +1427,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.InfoFormat( "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", item.Name, primLocalID, remoteClient.Name); - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); if (!Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) @@ -1522,7 +1522,7 @@ namespace OpenSim.Region.Framework.Scenes if (part.Inventory.UpdateInventoryItem(itemInfo)) { - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); } } } @@ -1574,7 +1574,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.InfoFormat("[PRIMINVENTORY]: " + // "Rezzed script {0} into prim local ID {1} for user {2}", // item.inventoryName, localID, remoteClient.Name); - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); part.ParentGroup.ResumeScripts(); } else @@ -1632,7 +1632,7 @@ namespace OpenSim.Region.Framework.Scenes taskItem.AssetID = asset.FullID; part.Inventory.AddInventoryItem(taskItem, false); - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); part.ParentGroup.ResumeScripts(); @@ -1746,7 +1746,7 @@ namespace OpenSim.Region.Framework.Scenes if (TryGetScenePresence(srcTaskItem.OwnerID, out avatar)) { - destPart.GetProperties(avatar.ControllingClient); + destPart.SendPropertiesToClient(avatar.ControllingClient); } } @@ -2084,7 +2084,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) continue; - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 29d01d6..270e582 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -144,7 +144,7 @@ namespace OpenSim.Region.Framework.Scenes { if (((SceneObjectGroup) ent).LocalId == primLocalID) { - ((SceneObjectGroup) ent).GetProperties(remoteClient); + ((SceneObjectGroup) ent).SendPropertiesToClient(remoteClient); ((SceneObjectGroup) ent).IsSelected = true; // A prim is only tainted if it's allowed to be edited by the person clicking it. if (Permissions.CanEditObject(((SceneObjectGroup)ent).UUID, remoteClient.AgentId) @@ -167,7 +167,7 @@ namespace OpenSim.Region.Framework.Scenes { if (part.LocalId == primLocalID) { - part.GetProperties(remoteClient); + part.SendPropertiesToClient(remoteClient); foundPrim = true; break; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 2819545..e7f2491 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1728,8 +1728,6 @@ namespace OpenSim.Region.Framework.Scenes #endregion - #region Scheduling - public override void Update() { // Check that the group was not deleted before the scheduled update @@ -1880,7 +1878,14 @@ namespace OpenSim.Region.Framework.Scenes parts[i].SendTerseUpdateToAllClients(); } - #endregion + /// + /// Send metadata about the root prim (name, description, sale price, etc.) to a client. + /// + /// + public void SendPropertiesToClient(IClientAPI client) + { + m_rootPart.SendPropertiesToClient(client); + } #region SceneGroupPart Methods @@ -2370,15 +2375,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Return metadata about a prim (name, description, sale price, etc.) - /// - /// - public void GetProperties(IClientAPI client) - { - m_rootPart.GetProperties(client); - } - - /// /// Set the name of a prim /// /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 04fef83..7203663 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1305,8 +1305,6 @@ namespace OpenSim.Region.Framework.Scenes #endregion Public Properties with only Get - #region Private Methods - private uint ApplyMask(uint val, bool set, uint mask) { if (set) @@ -1327,14 +1325,27 @@ namespace OpenSim.Region.Framework.Scenes m_updateFlag = 0; } - private void SendObjectPropertiesToClient(UUID AgentID) + /// + /// Send this part's properties (name, description, inventory serial, base mask, etc.) to a client + /// + /// + public void SendPropertiesToClient(IClientAPI client) + { + client.SendObjectPropertiesReply(this); + } + + /// + /// For the scene object group to which this part belongs, send that scene object's root part properties to a client. + /// + /// + private void SendRootPartPropertiesToClient(UUID AgentID) { m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) { // Ugly reference :( if (avatar.UUID == AgentID) { - m_parentGroup.GetProperties(avatar.ControllingClient); + m_parentGroup.SendPropertiesToClient(avatar.ControllingClient); } }); } @@ -1363,8 +1374,6 @@ namespace OpenSim.Region.Framework.Scenes // } // } - #endregion Private Methods - #region Public Methods public void ResetExpire() @@ -2030,11 +2039,6 @@ namespace OpenSim.Region.Framework.Scenes return Vector3.Zero; } - public void GetProperties(IClientAPI client) - { - client.SendObjectPropertiesReply(this); - } - /// /// Method for a prim to get it's world position from the group. /// @@ -3453,7 +3457,7 @@ namespace OpenSim.Region.Framework.Scenes { _groupID = groupID; if (client != null) - GetProperties(client); + SendPropertiesToClient(client); m_updateFlag = 2; } @@ -4273,10 +4277,10 @@ namespace OpenSim.Region.Framework.Scenes break; } - SendFullUpdateToAllClients(); - SendObjectPropertiesToClient(AgentID); + SendFullUpdateToAllClients(); + SendRootPartPropertiesToClient(AgentID); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d63b411..9446741 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -878,7 +878,7 @@ namespace OpenSim.Region.Framework.Scenes return; } - CreateInventoryFile(); + CreateInventoryFile(); // In principle, we should only do the rest if the inventory changed; // by sending m_inventorySerial to the client, it ought to know diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cf8517d..070cdc0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3591,7 +3591,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parentPrim.ScheduleGroupForFullUpdate(); if (client != null) - parentPrim.GetProperties(client); + parentPrim.SendPropertiesToClient(client); ScriptSleep(1000); } -- cgit v1.1 From c4efb97d49dec736151dfa3fa102efe6a5f6fbab Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 15 Sep 2011 22:59:29 +0100 Subject: Write code to create minimum necessary body parts/clothing and avatar entries to make a newly created user appear as a non-cloud on viewer 2 Viewer 2 no longer contains the default avatar assets (i.e. "Ruth") that would appear if the user had insufficient body part/clothing entries. Instead, avatars always appear as a cloud, which is a very bad experience for out-of-the-box OpenSim. Default is currently off. My intention is to switch it on for standalone shortly. This is not particularly flexible as "Ruth" is hardcoded, but this can change in the future, in co-ordination with the existing RemoteAdmin capabilities. Need to fix creation of suitable entries for users created as estate owners on standalone. Avatars still appear with spooky empty eyes, need to see if we can address this. This commit adds a "Default Iris" to the library (thanks to Eirynne Sieyes from http://opensimulator.org/mantis/view.php?id=1461) which can be used. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../UserAccountService/UserAccountService.cs | 152 ++++++++++++++- bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml | 10 +- bin/assets/BodyPartsAssetSet/base_eyes.dat | 26 +++ bin/assets/BodyPartsAssetSet/base_hair.dat | 26 +++ bin/assets/BodyPartsAssetSet/base_shape.dat | 212 +++++++++++++-------- bin/assets/BodyPartsAssetSet/newhair.dat | 63 ------ bin/assets/TexturesAssetSet/TexturesAssetSet.xml | 7 + bin/assets/TexturesAssetSet/default_iris.jp2 | Bin 0 -> 15719 bytes bin/config-include/Standalone.ini | 1 + .../TexturesLibrary/TexturesLibraryItems.xml | 10 + 12 files changed, 362 insertions(+), 148 deletions(-) create mode 100644 bin/assets/BodyPartsAssetSet/base_eyes.dat create mode 100644 bin/assets/BodyPartsAssetSet/base_hair.dat delete mode 100644 bin/assets/BodyPartsAssetSet/newhair.dat create mode 100644 bin/assets/TexturesAssetSet/default_iris.jp2 diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index b6a1564..c5a1828 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -467,7 +467,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return; } - // m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId); +// m_log.DebugFormat("[AVFACTORY]: Received request for wearables of {0}", client.Name); client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c5c9260..f394a95 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1237,6 +1237,7 @@ namespace OpenSim.Region.Framework.Scenes first, last); + m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", first, last); m_regInfo.EstateSettings.EstateOwner = account.PrincipalID; diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 8b8a8f9..21ce86c 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -28,15 +28,15 @@ using System; using System.Collections.Generic; using System.Reflection; +using log4net; using Nini.Config; +using OpenMetaverse; using OpenSim.Data; +using OpenSim.Framework; using OpenSim.Services.Interfaces; using OpenSim.Framework.Console; using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenMetaverse; -using log4net; - namespace OpenSim.Services.UserAccountService { public class UserAccountService : UserAccountServiceBase, IUserAccountService @@ -44,10 +44,16 @@ namespace OpenSim.Services.UserAccountService private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static UserAccountService m_RootInstance; + /// + /// Should we create default entries (minimum body parts/clothing, avatar wearable entries) for a new avatar? + /// + private bool m_CreateDefaultAvatarEntries; + protected IGridService m_GridService; protected IAuthenticationService m_AuthenticationService; protected IGridUserService m_GridUserService; protected IInventoryService m_InventoryService; + protected IAvatarService m_AvatarService; public UserAccountService(IConfigSource config) : base(config) @@ -77,6 +83,12 @@ namespace OpenSim.Services.UserAccountService if (invServiceDll != string.Empty) m_InventoryService = LoadPlugin(invServiceDll, new Object[] { config }); + string avatarServiceDll = userConfig.GetString("AvatarService", string.Empty); + if (avatarServiceDll != string.Empty) + m_AvatarService = LoadPlugin(avatarServiceDll, new Object[] { config }); + + m_CreateDefaultAvatarEntries = userConfig.GetBoolean("CreateDefaultAvatarEntries", false); + if (MainConsole.Instance != null) { MainConsole.Instance.Commands.AddCommand("UserService", false, @@ -102,9 +114,7 @@ namespace OpenSim.Services.UserAccountService "show account ", "Show account details for the given user", HandleShowAccount); } - } - } #region IUserAccountService @@ -493,12 +503,20 @@ namespace OpenSim.Services.UserAccountService { success = m_InventoryService.CreateUserInventory(account.PrincipalID); if (!success) + { m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.", firstName, lastName); + } + else if (m_CreateDefaultAvatarEntries) + { + CreateDefaultAppearanceEntries(account.PrincipalID); + } } m_log.InfoFormat("[USER ACCOUNT SERVICE]: Account {0} {1} created successfully", firstName, lastName); - } else { + } + else + { m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Account creation failed for account {0} {1}", firstName, lastName); } } @@ -507,5 +525,125 @@ namespace OpenSim.Services.UserAccountService m_log.ErrorFormat("[USER ACCOUNT SERVICE]: A user with the name {0} {1} already exists!", firstName, lastName); } } + + private void CreateDefaultAppearanceEntries(UUID principalID) + { + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID); + + InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Bodypart); + + InventoryItemBase eyes = new InventoryItemBase(UUID.Random(), principalID); + eyes.AssetID = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); + eyes.Name = "Default Eyes"; + eyes.CreatorId = principalID.ToString(); + eyes.AssetType = (int)AssetType.Bodypart; + eyes.InvType = (int)InventoryType.Wearable; + eyes.Folder = bodyPartsFolder.ID; + eyes.BasePermissions = (uint)PermissionMask.All; + eyes.CurrentPermissions = (uint)PermissionMask.All; + eyes.EveryOnePermissions = (uint)PermissionMask.All; + eyes.GroupPermissions = (uint)PermissionMask.All; + eyes.NextPermissions = (uint)PermissionMask.All; + eyes.Flags = (uint)WearableType.Eyes; + m_InventoryService.AddItem(eyes); + + InventoryItemBase shape = new InventoryItemBase(UUID.Random(), principalID); + shape.AssetID = AvatarWearable.DEFAULT_BODY_ASSET; + shape.Name = "Default Shape"; + shape.CreatorId = principalID.ToString(); + shape.AssetType = (int)AssetType.Bodypart; + shape.InvType = (int)InventoryType.Wearable; + shape.Folder = bodyPartsFolder.ID; + shape.BasePermissions = (uint)PermissionMask.All; + shape.CurrentPermissions = (uint)PermissionMask.All; + shape.EveryOnePermissions = (uint)PermissionMask.All; + shape.GroupPermissions = (uint)PermissionMask.All; + shape.NextPermissions = (uint)PermissionMask.All; + shape.Flags = (uint)WearableType.Shape; + m_InventoryService.AddItem(shape); + + InventoryItemBase skin = new InventoryItemBase(UUID.Random(), principalID); + skin.AssetID = AvatarWearable.DEFAULT_SKIN_ASSET; + skin.Name = "Default Skin"; + skin.CreatorId = principalID.ToString(); + skin.AssetType = (int)AssetType.Bodypart; + skin.InvType = (int)InventoryType.Wearable; + skin.Folder = bodyPartsFolder.ID; + skin.BasePermissions = (uint)PermissionMask.All; + skin.CurrentPermissions = (uint)PermissionMask.All; + skin.EveryOnePermissions = (uint)PermissionMask.All; + skin.GroupPermissions = (uint)PermissionMask.All; + skin.NextPermissions = (uint)PermissionMask.All; + skin.Flags = (uint)WearableType.Skin; + m_InventoryService.AddItem(skin); + + InventoryItemBase hair = new InventoryItemBase(UUID.Random(), principalID); + hair.AssetID = AvatarWearable.DEFAULT_HAIR_ASSET; + hair.Name = "Default Hair"; + hair.CreatorId = principalID.ToString(); + hair.AssetType = (int)AssetType.Bodypart; + hair.InvType = (int)InventoryType.Wearable; + hair.Folder = bodyPartsFolder.ID; + hair.BasePermissions = (uint)PermissionMask.All; + hair.CurrentPermissions = (uint)PermissionMask.All; + hair.EveryOnePermissions = (uint)PermissionMask.All; + hair.GroupPermissions = (uint)PermissionMask.All; + hair.NextPermissions = (uint)PermissionMask.All; + hair.Flags = (uint)WearableType.Hair; + m_InventoryService.AddItem(hair); + + InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Clothing); + + InventoryItemBase shirt = new InventoryItemBase(UUID.Random(), principalID); + shirt.AssetID = AvatarWearable.DEFAULT_SHIRT_ASSET; + shirt.Name = "Default Shirt"; + shirt.CreatorId = principalID.ToString(); + shirt.AssetType = (int)AssetType.Clothing; + shirt.InvType = (int)InventoryType.Wearable; + shirt.Folder = clothingFolder.ID; + shirt.BasePermissions = (uint)PermissionMask.All; + shirt.CurrentPermissions = (uint)PermissionMask.All; + shirt.EveryOnePermissions = (uint)PermissionMask.All; + shirt.GroupPermissions = (uint)PermissionMask.All; + shirt.NextPermissions = (uint)PermissionMask.All; + shirt.Flags = (uint)WearableType.Shirt; + m_InventoryService.AddItem(shirt); + + InventoryItemBase pants = new InventoryItemBase(UUID.Random(), principalID); + pants.AssetID = AvatarWearable.DEFAULT_PANTS_ASSET; + pants.Name = "Default Pants"; + pants.CreatorId = principalID.ToString(); + pants.AssetType = (int)AssetType.Clothing; + pants.InvType = (int)InventoryType.Wearable; + pants.Folder = clothingFolder.ID; + pants.BasePermissions = (uint)PermissionMask.All; + pants.CurrentPermissions = (uint)PermissionMask.All; + pants.EveryOnePermissions = (uint)PermissionMask.All; + pants.GroupPermissions = (uint)PermissionMask.All; + pants.NextPermissions = (uint)PermissionMask.All; + pants.Flags = (uint)WearableType.Pants; + m_InventoryService.AddItem(pants); + + if (m_AvatarService != null) + { + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default avatar entries for {0}", principalID); + + AvatarWearable[] wearables = new AvatarWearable[6]; + wearables[AvatarWearable.EYES] = new AvatarWearable(eyes.ID, eyes.AssetID); + wearables[AvatarWearable.BODY] = new AvatarWearable(shape.ID, shape.AssetID); + wearables[AvatarWearable.SKIN] = new AvatarWearable(skin.ID, skin.AssetID); + wearables[AvatarWearable.HAIR] = new AvatarWearable(hair.ID, hair.AssetID); + wearables[AvatarWearable.SHIRT] = new AvatarWearable(shirt.ID, shirt.AssetID); + wearables[AvatarWearable.PANTS] = new AvatarWearable(pants.ID, pants.AssetID); + + AvatarAppearance ap = new AvatarAppearance(); + for (int i = 0; i < 6; i++) + { + ap.SetWearable(i, wearables[i]); + } + + m_AvatarService.SetAppearance(principalID, ap); + } + } } -} +} \ No newline at end of file diff --git a/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml b/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml index 8ef0fe7..a3d7ba3 100644 --- a/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml +++ b/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml @@ -4,7 +4,7 @@ - +
@@ -34,6 +34,14 @@
+ +
+ + + + +
+ {2}", nameA, nameB, - //needsCollision); - - - return needsCollision; - } - //added by jed zhu - //calculas the collision between the Prim and Actor - // - private int Collision(BulletXCharacter actorA, BulletXPrim primB) - { - int[] indexBase; - Vector3[] vertexBase; - Vector3 vNormal; - // Vector3 vP1; - // Vector3 vP2; - // Vector3 vP3; - IMesh mesh = primB.GetMesh(); - - float fdistance; - if (primB == null) - return 3; - if (mesh == null) - return 2; - if (actorA == null) - return 3; - - int iVertexCount = mesh.getVertexList().Count; - int iIndexCount = mesh.getIndexListAsInt().Length; - if (iVertexCount == 0) - return 3; - if (iIndexCount == 0) - return 3; - lock (BulletXScene.BulletXLock) - { - indexBase = mesh.getIndexListAsInt(); - vertexBase = new Vector3[iVertexCount]; - - for (int i = 0; i < iVertexCount; i++) - { - OpenMetaverse.Vector3 v = mesh.getVertexList()[i]; - if (v != null) // Note, null has special meaning. See meshing code for details - vertexBase[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); - else - vertexBase[i] = Vector3.Zero; - } - - for (int ix = 0; ix < iIndexCount; ix += 3) - { - int ia = indexBase[ix + 0]; - int ib = indexBase[ix + 1]; - int ic = indexBase[ix + 2]; - // - Vector3 v1 = vertexBase[ib] - vertexBase[ia]; - Vector3 v2 = vertexBase[ic] - vertexBase[ia]; - - Vector3.Cross(ref v1, ref v2, out vNormal); - Vector3.Normalize(ref vNormal, out vNormal); - - fdistance = Vector3.Dot(vNormal, vertexBase[ia]) + 0.50f; - if (preCheckCollision(actorA, vNormal, fdistance) == 1) - { - if (CheckCollision(actorA, ia, ib, ic, vNormal, vertexBase) == 1) - { - //PhysicsVector v = actorA.Position; - //Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v); - //Vector3 vp = vNormal * (fdistance - Vector3.Dot(vNormal, v3) + 0.2f); - //actorA.Position += BulletXMaths.XnaVector3ToPhysicsVector(vp); - return 1; - } - } - } - } - - - return 0; - } - //added by jed zhu - //return value 1: need second check - //return value 0: no need check - - private int preCheckCollision(BulletXActor actA, Vector3 vNormal, float fDist) - { - float fstartSide; - OpenMetaverse.Vector3 v = actA.Position; - Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v); - - fstartSide = Vector3.Dot(vNormal, v3) - fDist; - if (fstartSide > 0) return 0; - else return 1; - } - //added by jed zhu - private int CheckCollision(BulletXActor actA, int ia, int ib, int ic, Vector3 vNormal, Vector3[] vertBase) - { - Vector3 perPlaneNormal; - float fPerPlaneDist; - OpenMetaverse.Vector3 v = actA.Position; - Vector3 v3 = BulletXMaths.PhysicsVectorToXnaVector3(v); - //check AB - Vector3 v1; - v1 = vertBase[ib] - vertBase[ia]; - Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal); - Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal); - - if (Vector3.Dot((vertBase[ic] - vertBase[ia]), perPlaneNormal) < 0) - perPlaneNormal = -perPlaneNormal; - fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ia]) - 0.50f; - - - - if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0) - return 0; - fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ic]) + 0.50f; - if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0) - return 0; - - //check BC - - v1 = vertBase[ic] - vertBase[ib]; - Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal); - Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal); - - if (Vector3.Dot((vertBase[ia] - vertBase[ib]), perPlaneNormal) < 0) - perPlaneNormal = -perPlaneNormal; - fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ib]) - 0.50f; - - - if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0) - return 0; - fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ia]) + 0.50f; - if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0) - return 0; - //check CA - v1 = vertBase[ia] - vertBase[ic]; - Vector3.Cross(ref vNormal, ref v1, out perPlaneNormal); - Vector3.Normalize(ref perPlaneNormal, out perPlaneNormal); - - if (Vector3.Dot((vertBase[ib] - vertBase[ic]), perPlaneNormal) < 0) - perPlaneNormal = -perPlaneNormal; - fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ic]) - 0.50f; - - - if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) < 0) - return 0; - fPerPlaneDist = Vector3.Dot(perPlaneNormal, vertBase[ib]) + 0.50f; - if ((Vector3.Dot(perPlaneNormal, v3) - fPerPlaneDist) > 0) - return 0; - - return 1; - - } - } - - /// - /// PhysicsScene Class for BulletX - /// - public class BulletXScene : PhysicsScene - { - #region BulletXScene Fields - - public DiscreteDynamicsWorld ddWorld; - private CollisionDispatcher cDispatcher; - private OverlappingPairCache opCache; - private SequentialImpulseConstraintSolver sicSolver; - public static Object BulletXLock = new Object(); - - private const int minXY = 0; - private const int minZ = 0; - private const int maxXY = (int)Constants.RegionSize; - private const int maxZ = 4096; - private const int maxHandles = 32766; //Why? I don't know - private const float gravity = 9.8f; - private const float heightLevel0 = 77.0f; - private const float heightLevel1 = 200.0f; - private const float lowGravityFactor = 0.2f; - //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS - private const int simulationSubSteps = 10; - //private float[] _heightmap; - private BulletXPlanet _simFlatPlanet; - internal Dictionary _characters = new Dictionary(); - internal Dictionary _prims = new Dictionary(); - - public IMesher mesher; - // private IConfigSource m_config; - - // protected internal String identifier; - - public BulletXScene(String sceneIdentifier) - { - //identifier = sceneIdentifier; - cDispatcher = new CollisionDispatcherLocal(this); - Vector3 worldMinDim = new Vector3((float)minXY, (float)minXY, (float)minZ); - Vector3 worldMaxDim = new Vector3((float)maxXY, (float)maxXY, (float)maxZ); - opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); - sicSolver = new SequentialImpulseConstraintSolver(); - - lock (BulletXLock) - { - ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); - ddWorld.Gravity = new Vector3(0, 0, -gravity); - } - //this._heightmap = new float[65536]; - } - - public static float Gravity - { - get { return gravity; } - } - - public static float HeightLevel0 - { - get { return heightLevel0; } - } - - public static float HeightLevel1 - { - get { return heightLevel1; } - } - - public static float LowGravityFactor - { - get { return lowGravityFactor; } - } - - public static int MaxXY - { - get { return maxXY; } - } - - public static int MaxZ - { - get { return maxZ; } - } - - private List _forgottenRigidBodies = new List(); - internal string is_ex_message = "Can't remove rigidBody!: "; - - #endregion - - public BulletXScene() - { - cDispatcher = new CollisionDispatcherLocal(this); - Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); - Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); - opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); - sicSolver = new SequentialImpulseConstraintSolver(); - - lock (BulletXLock) - { - ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); - ddWorld.Gravity = new Vector3(0, 0, -gravity); - } - //this._heightmap = new float[65536]; - } - - public override void Initialise(IMesher meshmerizer, IConfigSource config) - { - mesher = meshmerizer; - // m_config = config; - } - - public override void Dispose() - { - - } - - public override Dictionary GetTopColliders() - { - Dictionary returncolliders = new Dictionary(); - return returncolliders; - } - - public override void SetWaterLevel(float baseheight) - { - - } - - public override PhysicsActor AddAvatar(string avName, OpenMetaverse.Vector3 position, OpenMetaverse.Vector3 size, bool isFlying) - { - OpenMetaverse.Vector3 pos = OpenMetaverse.Vector3.Zero; - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z + 20; - BulletXCharacter newAv = null; - lock (BulletXLock) - { - newAv = new BulletXCharacter(avName, this, pos); - _characters.Add(newAv.RigidBody, newAv); - } - newAv.Flying = isFlying; - return newAv; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - if (actor is BulletXCharacter) - { - lock (BulletXLock) - { - try - { - ddWorld.RemoveRigidBody(((BulletXCharacter) actor).RigidBody); - } - catch (Exception ex) - { - BulletXMessage(is_ex_message + ex.Message, true); - ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; - AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); - } - _characters.Remove(((BulletXCharacter) actor).RigidBody); - } - GC.Collect(); - } - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, OpenMetaverse.Vector3 position, - OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation, bool isPhysical, uint localid) - { - PhysicsActor result; - - switch (pbs.ProfileShape) - { - case ProfileShape.Square: - /// support simple box & hollow box now; later, more shapes - if (pbs.ProfileHollow == 0) - { - result = AddPrim(primName, position, size, rotation, null, null, isPhysical); - } - else - { - IMesh mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); - result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); - } - break; - - default: - result = AddPrim(primName, position, size, rotation, null, null, isPhysical); - break; - } - - return result; - } - - public PhysicsActor AddPrim(String name, OpenMetaverse.Vector3 position, OpenMetaverse.Vector3 size, OpenMetaverse.Quaternion rotation, - IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) - { - BulletXPrim newPrim = null; - lock (BulletXLock) - { - newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); - _prims.Add(newPrim.RigidBody, newPrim); - } - return newPrim; - } - - public override void RemovePrim(PhysicsActor prim) - { - if (prim is BulletXPrim) - { - lock (BulletXLock) - { - try - { - ddWorld.RemoveRigidBody(((BulletXPrim) prim).RigidBody); - } - catch (Exception ex) - { - BulletXMessage(is_ex_message + ex.Message, true); - ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; - AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); - } - _prims.Remove(((BulletXPrim) prim).RigidBody); - } - GC.Collect(); - } - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0; - lock (BulletXLock) - { - //Try to remove garbage - RemoveForgottenRigidBodies(); - //End of remove - MoveAPrimitives(timeStep); - - - fps = (timeStep*simulationSubSteps); - - ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep); - //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine. - ValidateHeightForAll(); - //End heightmap validation. - UpdateKineticsForAll(); - } - return fps; - } - - private void MoveAPrimitives(float timeStep) - { - foreach (BulletXCharacter actor in _characters.Values) - { - actor.Move(timeStep); - } - } - - private void ValidateHeightForAll() - { - float _height; - foreach (BulletXCharacter actor in _characters.Values) - { - //_height = HeightValue(actor.RigidBodyPosition); - _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); - actor.ValidateHeight(_height); - //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); - } - foreach (BulletXPrim prim in _prims.Values) - { - //_height = HeightValue(prim.RigidBodyPosition); - _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); - prim.ValidateHeight(_height); - //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height); - } - //foreach (BulletXCharacter actor in _characters) - //{ - // actor.ValidateHeight(0); - //} - //foreach (BulletXPrim prim in _prims) - //{ - // prim.ValidateHeight(0); - //} - } - - private void UpdateKineticsForAll() - { - //UpdatePosition > UpdateKinetics. - //Not only position will be updated, also velocity cause acceleration. - foreach (BulletXCharacter actor in _characters.Values) - { - actor.UpdateKinetics(); - } - foreach (BulletXPrim prim in _prims.Values) - { - prim.UpdateKinetics(); - } - //if (this._simFlatPlanet!=null) this._simFlatPlanet.Restore(); - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get - { - return (false); // for now we won't be multithreaded - } - } - - public override void SetTerrain(float[] heightMap) - { - ////As the same as ODE, heightmap (x,y) must be swapped for BulletX - //for (int i = 0; i < 65536; i++) - //{ - // // this._heightmap[i] = (double)heightMap[i]; - // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) - // int x = i & 0xff; - // int y = i >> 8; - // this._heightmap[i] = heightMap[x * 256 + y]; - //} - - //float[] swappedHeightMap = new float[65536]; - ////As the same as ODE, heightmap (x,y) must be swapped for BulletX - //for (int i = 0; i < 65536; i++) - //{ - // // this._heightmap[i] = (double)heightMap[i]; - // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) - // int x = i & 0xff; - // int y = i >> 8; - // swappedHeightMap[i] = heightMap[x * 256 + y]; - //} - DeleteTerrain(); - //There is a BulletXLock inside the constructor of BulletXPlanet - //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap); - _simFlatPlanet = new BulletXPlanet(this, heightMap); - //this._heightmap = heightMap; - } - - public override void DeleteTerrain() - { - if (_simFlatPlanet != null) - { - lock (BulletXLock) - { - try - { - ddWorld.RemoveRigidBody(_simFlatPlanet.RigidBody); - } - catch (Exception ex) - { - BulletXMessage(is_ex_message + ex.Message, true); - _simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation; - AddForgottenRigidBody(_simFlatPlanet.RigidBody); - } - } - _simFlatPlanet = null; - GC.Collect(); - BulletXMessage("Terrain erased!", false); - } - - - - //this._heightmap = null; - } - - - - internal void AddForgottenRigidBody(RigidBody forgottenRigidBody) - { - _forgottenRigidBodies.Add(forgottenRigidBody); - } - - private void RemoveForgottenRigidBodies() - { - RigidBody forgottenRigidBody; - int nRigidBodies = _forgottenRigidBodies.Count; - for (int i = nRigidBodies - 1; i >= 0; i--) - { - forgottenRigidBody = _forgottenRigidBodies[i]; - try - { - ddWorld.RemoveRigidBody(forgottenRigidBody); - _forgottenRigidBodies.Remove(forgottenRigidBody); - BulletXMessage("Forgotten Rigid Body Removed", false); - } - catch (Exception ex) - { - BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false); - } - } - GC.Collect(); - } - - internal static void BulletXMessage(string message, bool isWarning) - { - PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning); - } - - //temp - //private float HeightValue(MonoXnaCompactMaths.Vector3 position) - //{ - // int li_x, li_y; - // float height; - // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0; - // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0; - - // height = this._heightmap[li_y * 256 + li_x]; - // if (height < 0) height = 0; - // else if (height > maxZ) height = maxZ; - - // return height; - //} - } - - /// - /// Generic Physics Actor for BulletX inherit from PhysicActor - /// - public class BulletXActor : PhysicsActor - { - protected bool flying = false; - protected bool _physical = false; - protected OpenMetaverse.Vector3 _position; - protected OpenMetaverse.Vector3 _velocity; - protected OpenMetaverse.Vector3 _size; - protected OpenMetaverse.Vector3 _acceleration; - protected OpenMetaverse.Quaternion _orientation; - protected OpenMetaverse.Vector3 m_rotationalVelocity; - protected RigidBody rigidBody; - protected int m_PhysicsActorType; - private Boolean iscolliding = false; - internal string _name; - - public BulletXActor(String name) - { - _name = name; - } - - public override bool Stopped - { - get { return false; } - } - - public override OpenMetaverse.Vector3 Position - { - get { return _position; } - set - { - lock (BulletXScene.BulletXLock) - { - _position = value; - Translate(); - } - } - } - - public override OpenMetaverse.Vector3 RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override OpenMetaverse.Vector3 Velocity - { - get { return _velocity; } - set - { - lock (BulletXScene.BulletXLock) - { - //Static objects don' have linear velocity - if (_physical) - { - _velocity = value; - Speed(); - } - else - { - _velocity = OpenMetaverse.Vector3.Zero; - } - } - } - } - public override float CollisionScore - { - get { return 0f; } - set { } - } - public override OpenMetaverse.Vector3 Size - { - get { return _size; } - set - { - lock (BulletXScene.BulletXLock) - { - _size = value; - } - } - } - - public override OpenMetaverse.Vector3 Force - { - get { return OpenMetaverse.Vector3.Zero; } - set { return; } - } - - public override int VehicleType - { - get { return 0; } - set { return; } - } - - public override void VehicleFloatParam(int param, float value) - { - - } - - public override void VehicleVectorParam(int param, OpenMetaverse.Vector3 value) - { - - } - - public override void VehicleRotationParam(int param, OpenMetaverse.Quaternion rotation) - { - - } - - public override void VehicleFlags(int param, bool remove) - { - - } - - public override void SetVolumeDetect(int param) - { - - } - - public override OpenMetaverse.Vector3 CenterOfMass - { - get { return OpenMetaverse.Vector3.Zero; } - } - - public override OpenMetaverse.Vector3 GeometricCenter - { - get { return OpenMetaverse.Vector3.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override OpenMetaverse.Vector3 Acceleration - { - get { return _acceleration; } - } - - public override OpenMetaverse.Quaternion Orientation - { - get { return _orientation; } - set - { - lock (BulletXScene.BulletXLock) - { - _orientation = value; - ReOrient(); - } - } - } - public override void link(PhysicsActor obj) - { - - } - - public override void delink() - { - - } - - public override void LockAngularMotion(OpenMetaverse.Vector3 axis) - { - - } - - public override float Mass - { - get { return ActorMass; } - } - - public virtual float ActorMass - { - get { return 0; } - } - - public override int PhysicsActorType - { - get { return (int) m_PhysicsActorType; } - set { m_PhysicsActorType = value; } - } - - public RigidBody RigidBody - { - get { return rigidBody; } - } - - public Vector3 RigidBodyPosition - { - get { return rigidBody.CenterOfMassPosition; } - } - - public override bool IsPhysical - { - get { return _physical; } - set { _physical = value; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override uint LocalID - { - set { return; } - } - - public override bool Grabbed - { - set { return; } - } - - public override bool Selected - { - set { return; } - } - - public override float Buoyancy - { - get { return 0f; } - set { return; } - } - - public override bool FloatOnWater - { - set { return; } - } - - public virtual void SetAcceleration(OpenMetaverse.Vector3 accel) - { - lock (BulletXScene.BulletXLock) - { - _acceleration = accel; - } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce) - { - } - public override OpenMetaverse.Vector3 Torque - { - get { return OpenMetaverse.Vector3.Zero; } - set { return; } - } - public override void AddAngularForce(OpenMetaverse.Vector3 force, bool pushforce) - { - } - - public override void SetMomentum(OpenMetaverse.Vector3 momentum) - { - } - - internal virtual void ValidateHeight(float heighmapPositionValue) - { - } - - internal virtual void UpdateKinetics() - { - } - - #region Methods for updating values of RigidBody - - protected internal void Translate() - { - Translate(_position); - } - - protected internal void Translate(OpenMetaverse.Vector3 _newPos) - { - Vector3 _translation; - _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition; - rigidBody.Translate(_translation); - } - - protected internal void Speed() - { - Speed(_velocity); - } - - protected internal void Speed(OpenMetaverse.Vector3 _newSpeed) - { - Vector3 _speed; - _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed); - rigidBody.LinearVelocity = _speed; - } - - protected internal void ReOrient() - { - ReOrient(_orientation); - } - - protected internal void ReOrient(OpenMetaverse.Quaternion _newOrient) - { - Quaternion _newOrientation; - _newOrientation = BulletXMaths.QuaternionToXnaQuaternion(_newOrient); - Matrix _comTransform = rigidBody.CenterOfMassTransform; - BulletXMaths.SetRotation(ref _comTransform, _newOrientation); - rigidBody.CenterOfMassTransform = _comTransform; - } - - protected internal void ReSize() - { - ReSize(_size); - } - - protected internal virtual void ReSize(OpenMetaverse.Vector3 _newSize) - { - } - - public virtual void ScheduleTerseUpdate() - { - base.RequestPhysicsterseUpdate(); - } - - #endregion - - public override void CrossingFailure() - { - - } - public override OpenMetaverse.Vector3 PIDTarget { set { return; } } - public override bool PIDActive { set { return; } } - public override float PIDTau { set { return; } } - - public override float PIDHoverHeight { set { return; } } - public override bool PIDHoverActive { set { return; } } - public override PIDHoverType PIDHoverType { set { return; } } - public override float PIDHoverTau { set { return; } } - - public override OpenMetaverse.Quaternion APIDTarget - { - set { return; } - } - - public override bool APIDActive - { - set { return; } - } - - public override float APIDStrength - { - set { return; } - } - - public override float APIDDamping - { - set { return; } - } - - - public override void SubscribeEvents(int ms) - { - - } - public override void UnSubscribeEvents() - { - - } - public override bool SubscribedEvents() - { - return false; - } - } - - /// - /// PhysicsActor Character Class for BulletX - /// - public class BulletXCharacter : BulletXActor - { - public BulletXCharacter(BulletXScene parent_scene, OpenMetaverse.Vector3 pos) - : this(String.Empty, parent_scene, pos) - { - } - - public BulletXCharacter(String avName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos) - : this(avName, parent_scene, pos, OpenMetaverse.Vector3.Zero, OpenMetaverse.Vector3.Zero, OpenMetaverse.Vector3.Zero, - OpenMetaverse.Quaternion.Identity) - { - } - - public BulletXCharacter(String avName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 velocity, - OpenMetaverse.Vector3 size, OpenMetaverse.Vector3 acceleration, OpenMetaverse.Quaternion orientation) - : base(avName) - { - //This fields will be removed. They're temporal - float _sizeX = 0.5f; - float _sizeY = 0.5f; - float _sizeZ = 1.6f; - //. - _position = pos; - _velocity = velocity; - _size = size; - //--- - _size.X = _sizeX; - _size.Y = _sizeY; - _size.Z = _sizeZ; - //. - _acceleration = acceleration; - _orientation = orientation; - _physical = true; - - float _mass = 50.0f; //This depends of avatar's dimensions - //For RigidBody Constructor. The next values might change - float _linearDamping = 0.0f; - float _angularDamping = 0.0f; - float _friction = 0.5f; - float _restitution = 0.0f; - Matrix _startTransform = Matrix.Identity; - Matrix _centerOfMassOffset = Matrix.Identity; - lock (BulletXScene.BulletXLock) - { - _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); - //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f)); - //For now, like ODE, collisionShape = sphere of radious = 1.0 - CollisionShape _collisionShape = new SphereShape(1.0f); - DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); - Vector3 _localInertia = new Vector3(); - _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 - rigidBody = - new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, - _friction, _restitution); - //rigidBody.ActivationState = ActivationState.DisableDeactivation; - //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition - Vector3 _vDebugTranslation; - _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; - rigidBody.Translate(_vDebugTranslation); - parent_scene.ddWorld.AddRigidBody(rigidBody); - } - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override OpenMetaverse.Vector3 Position - { - get { return base.Position; } - set { base.Position = value; } - } - - public override OpenMetaverse.Vector3 Velocity - { - get { return base.Velocity; } - set { base.Velocity = value; } - } - - public override OpenMetaverse.Vector3 Size - { - get { return base.Size; } - set { base.Size = value; } - } - - public override OpenMetaverse.Vector3 Acceleration - { - get { return base.Acceleration; } - } - - public override OpenMetaverse.Quaternion Orientation - { - get { return base.Orientation; } - set { base.Orientation = value; } - } - - public override bool Flying - { - get { return base.Flying; } - set { base.Flying = value; } - } - - public override bool IsColliding - { - get { return base.IsColliding; } - set { base.IsColliding = value; } - } - - public override bool Kinematic - { - get { return base.Kinematic; } - set { base.Kinematic = value; } - } - - public override void SetAcceleration(OpenMetaverse.Vector3 accel) - { - base.SetAcceleration(accel); - } - - public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce) - { - base.AddForce(force, pushforce); - } - - public override void SetMomentum(OpenMetaverse.Vector3 momentum) - { - base.SetMomentum(momentum); - } - - internal void Move(float timeStep) - { - Vector3 vec = new Vector3(); - //At this point it's supossed that: - //_velocity == rigidBody.LinearVelocity - vec.X = _velocity.X; - vec.Y = _velocity.Y; - vec.Z = _velocity.Z; - if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate(); - if (flying) - { - //Antigravity with movement - if (_position.Z <= BulletXScene.HeightLevel0) - { - vec.Z += BulletXScene.Gravity*timeStep; - } - //Lowgravity with movement - else if ((_position.Z > BulletXScene.HeightLevel0) - && (_position.Z <= BulletXScene.HeightLevel1)) - { - vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); - } - //Lowgravity with... - else if (_position.Z > BulletXScene.HeightLevel1) - { - if (vec.Z > 0) //no movement - vec.Z = BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); - else - vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); - } - } - rigidBody.LinearVelocity = vec; - } - - //This validation is very basic - internal override void ValidateHeight(float heighmapPositionValue) - { - if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) - { - Matrix m = rigidBody.WorldTransform; - Vector3 v3 = m.Translation; - v3.Z = heighmapPositionValue + _size.Z/2.0f; - m.Translation = v3; - rigidBody.WorldTransform = m; - //When an Avie touch the ground it's vertical velocity it's reduced to ZERO - Speed(new OpenMetaverse.Vector3(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); - } - } - - internal override void UpdateKinetics() - { - _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); - _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); - //Orientation it seems that it will be the default. - ReOrient(); - } - } - - /// - /// PhysicsActor Prim Class for BulletX - /// - public class BulletXPrim : BulletXActor - { - //Density it will depends of material. - //For now all prims have the same density, all prims are made of water. Be water my friend! :D - private const float _density = 1000.0f; - private BulletXScene _parent_scene; - private OpenMetaverse.Vector3 m_prev_position; - private bool m_lastUpdateSent = false; - //added by jed zhu - private IMesh _mesh; - public IMesh GetMesh() { return _mesh; } - - - - public BulletXPrim(String primName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 size, - OpenMetaverse.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) - : this( - primName, parent_scene, pos, OpenMetaverse.Vector3.Zero, size, OpenMetaverse.Vector3.Zero, rotation, mesh, pbs, - isPhysical) - { - } - - public BulletXPrim(String primName, BulletXScene parent_scene, OpenMetaverse.Vector3 pos, OpenMetaverse.Vector3 velocity, - OpenMetaverse.Vector3 size, - OpenMetaverse.Vector3 acceleration, OpenMetaverse.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, - bool isPhysical) - : base(primName) - { - if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) - throw new Exception("Size 0"); - if (OpenMetaverse.Quaternion.Normalize(rotation).Length() == 0f) - rotation = OpenMetaverse.Quaternion.Identity; - - _position = pos; - _physical = isPhysical; - _velocity = _physical ? velocity : OpenMetaverse.Vector3.Zero; - _size = size; - _acceleration = acceleration; - _orientation = rotation; - - _parent_scene = parent_scene; - - CreateRigidBody(parent_scene, mesh, pos, size); - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Prim; } - set { return; } - } - - public override OpenMetaverse.Vector3 Position - { - get { return base.Position; } - set { base.Position = value; } - } - - public override OpenMetaverse.Vector3 Velocity - { - get { return base.Velocity; } - set { base.Velocity = value; } - } - - public override OpenMetaverse.Vector3 Size - { - get { return _size; } - set - { - lock (BulletXScene.BulletXLock) - { - _size = value; - ReSize(); - } - } - } - - public override OpenMetaverse.Vector3 Acceleration - { - get { return base.Acceleration; } - } - - public override OpenMetaverse.Quaternion Orientation - { - get { return base.Orientation; } - set { base.Orientation = value; } - } - - public override float ActorMass - { - get - { - //For now all prims are boxes - return (_physical ? 1 : 0)*_density*_size.X*_size.Y*_size.Z; - } - } - - public override bool IsPhysical - { - get { return base.IsPhysical; } - set - { - base.IsPhysical = value; - if (value) - { - //--- - PhysicsPluginManager.PhysicsPluginMessage("Physical - Recreate", true); - //--- - ReCreateRigidBody(_size); - } - else - { - //--- - PhysicsPluginManager.PhysicsPluginMessage("Physical - SetMassProps", true); - //--- - rigidBody.SetMassProps(Mass, new Vector3()); - } - } - } - - public override bool Flying - { - get { return base.Flying; } - set { base.Flying = value; } - } - - public override bool IsColliding - { - get { return base.IsColliding; } - set { base.IsColliding = value; } - } - - public override bool Kinematic - { - get { return base.Kinematic; } - set { base.Kinematic = value; } - } - - public override void SetAcceleration(OpenMetaverse.Vector3 accel) - { - lock (BulletXScene.BulletXLock) - { - _acceleration = accel; - } - } - - public override void AddForce(OpenMetaverse.Vector3 force, bool pushforce) - { - base.AddForce(force,pushforce); - } - - public override void SetMomentum(OpenMetaverse.Vector3 momentum) - { - base.SetMomentum(momentum); - } - - internal override void ValidateHeight(float heighmapPositionValue) - { - if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) - { - Matrix m = rigidBody.WorldTransform; - Vector3 v3 = m.Translation; - v3.Z = heighmapPositionValue + _size.Z/2.0f; - m.Translation = v3; - rigidBody.WorldTransform = m; - //When a Prim touch the ground it's vertical velocity it's reduced to ZERO - //Static objects don't have linear velocity - if (_physical) - Speed(new OpenMetaverse.Vector3(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); - } - } - - internal override void UpdateKinetics() - { - if (_physical) //Updates properties. Prim updates its properties physically - { - _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); - - _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); - _orientation = BulletXMaths.XnaQuaternionToQuaternion(rigidBody.Orientation); - - if ((Math.Abs(m_prev_position.X - _position.X) < 0.03) - && (Math.Abs(m_prev_position.Y - _position.Y) < 0.03) - && (Math.Abs(m_prev_position.Z - _position.Z) < 0.03)) - { - if (!m_lastUpdateSent) - { - _velocity = OpenMetaverse.Vector3.Zero; - base.ScheduleTerseUpdate(); - m_lastUpdateSent = true; - } - } - else - { - m_lastUpdateSent = false; - base.ScheduleTerseUpdate(); - } - m_prev_position = _position; - } - else //Doesn't updates properties. That's a cancel - { - Translate(); - //Speed(); //<- Static objects don't have linear velocity - ReOrient(); - } - } - - #region Methods for updating values of RigidBody - - protected internal void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, OpenMetaverse.Vector3 pos, - OpenMetaverse.Vector3 size) - { - //For RigidBody Constructor. The next values might change - float _linearDamping = 0.0f; - float _angularDamping = 0.0f; - float _friction = 1.0f; - float _restitution = 0.0f; - Matrix _startTransform = Matrix.Identity; - Matrix _centerOfMassOffset = Matrix.Identity; - //added by jed zhu - _mesh = mesh; - - lock (BulletXScene.BulletXLock) - { - _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); - //For now all prims are boxes - CollisionShape _collisionShape; - if (mesh == null) - { - _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size)/2.0f); - } - else - { - int iVertexCount = mesh.getVertexList().Count; - int[] indices = mesh.getIndexListAsInt(); - Vector3[] v3Vertices = new Vector3[iVertexCount]; - for (int i = 0; i < iVertexCount; i++) - { - OpenMetaverse.Vector3 v = mesh.getVertexList()[i]; - if (v != null) // Note, null has special meaning. See meshing code for details - v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); - else - v3Vertices[i] = Vector3.Zero; - } - TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices); - - _collisionShape = new TriangleMeshShape(triMesh); - } - DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); - Vector3 _localInertia = new Vector3(); - if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 - rigidBody = - new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, - _friction, _restitution); - //rigidBody.ActivationState = ActivationState.DisableDeactivation; - //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition - Vector3 _vDebugTranslation; - _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; - rigidBody.Translate(_vDebugTranslation); - //--- - parent_scene.ddWorld.AddRigidBody(rigidBody); - } - } - - protected internal void ReCreateRigidBody(OpenMetaverse.Vector3 size) - { - //There is a bug when trying to remove a rigidBody that is colliding with something.. - try - { - _parent_scene.ddWorld.RemoveRigidBody(rigidBody); - } - catch (Exception ex) - { - BulletXScene.BulletXMessage(_parent_scene.is_ex_message + ex.Message, true); - rigidBody.ActivationState = ActivationState.DisableSimulation; - _parent_scene.AddForgottenRigidBody(rigidBody); - } - CreateRigidBody(_parent_scene, null, _position, size); - // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler - if (_physical) Speed(); //Static objects don't have linear velocity - ReOrient(); - GC.Collect(); - } - - protected internal override void ReSize(OpenMetaverse.Vector3 _newSize) - { - //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't - //so i have to do it manually. That's recreating rigidbody - ReCreateRigidBody(_newSize); - } - - #endregion - } - - /// - /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene - /// - internal class BulletXPlanet - { - private OpenMetaverse.Vector3 _staticPosition; -// private Vector3 _staticVelocity; -// private OpenMetaverse.Quaternion _staticOrientation; - private float _mass; - // private BulletXScene _parentscene; - internal float[] _heightField; - private RigidBody _flatPlanet; - - internal RigidBody RigidBody - { - get { return _flatPlanet; } - } - - internal BulletXPlanet(BulletXScene parent_scene, float[] heightField) - { - _staticPosition = new OpenMetaverse.Vector3(BulletXScene.MaxXY / 2, BulletXScene.MaxXY / 2, 0); -// _staticVelocity = new PhysicsVector(); -// _staticOrientation = OpenMetaverse.Quaternion.Identity; - _mass = 0; //No active - // _parentscene = parent_scene; - _heightField = heightField; - - float _linearDamping = 0.0f; - float _angularDamping = 0.0f; - float _friction = 0.5f; - float _restitution = 0.0f; - Matrix _startTransform = Matrix.Identity; - Matrix _centerOfMassOffset = Matrix.Identity; - - lock (BulletXScene.BulletXLock) - { - try - { - _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition); - CollisionShape _collisionShape = - new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField, - (float) BulletXScene.MaxZ, 2, true, false); - DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); - Vector3 _localInertia = new Vector3(); - //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 - _flatPlanet = - new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, - _angularDamping, _friction, _restitution); - //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition - Vector3 _vDebugTranslation; - _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition; - _flatPlanet.Translate(_vDebugTranslation); - parent_scene.ddWorld.AddRigidBody(_flatPlanet); - } - catch (Exception ex) - { - BulletXScene.BulletXMessage(ex.Message, true); - } - } - BulletXScene.BulletXMessage("BulletXPlanet created.", false); - } - - internal float HeightValue(Vector3 position) - { - int li_x, li_y; - float height; - li_x = (int) Math.Round(position.X); - if (li_x < 0) li_x = 0; - if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1; - li_y = (int) Math.Round(position.Y); - if (li_y < 0) li_y = 0; - if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1; - - height = ((HeightfieldTerrainShape) _flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y); - if (height < 0) height = 0; - else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ; - - return height; - } - } -} diff --git a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs deleted file mode 100644 index 637cf6e..0000000 --- a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs +++ /dev/null @@ -1,197 +0,0 @@ -/* - Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru - Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/* - This file contains a class TriangleIndexVertexArray. I tried using the class with the same name - from the BulletX implementation and found it unusable for the purpose of using triangle meshes - within BulletX as the implementation was painfully incomplete. - The attempt to derive from the original class failed as viable members were hidden. - Fiddling around with BulletX itself was not my intention. - So I copied the class to the BulletX-plugin and modified it. - If you want to fiddle around with it it's up to you to move all this to BulletX. - If someone someday implements the missing functionality in BulletX, feel free to remove this class. - It's just an ugly hack. -*/ - -using System; -using System.Collections.Generic; -using MonoXnaCompactMaths; -using XnaDevRu.BulletX; - -namespace OpenSim.Region.Physics.BulletXPlugin -{ - /// - /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements - /// instead of the number of indices, we pass the number of triangles - /// - public struct IndexedMesh - { - private int _numTriangles; - private int[] _triangleIndexBase; - private int _triangleIndexStride; - private int _numVertices; - private Vector3[] _vertexBase; - private int _vertexStride; - - public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, - Vector3[] vertexBase, int vertexStride) - { - _numTriangles = numTriangleIndices; - _triangleIndexBase = triangleIndexBase; - _triangleIndexStride = triangleIndexStride; - _vertexBase = vertexBase; - _numVertices = numVertices; - _vertexStride = vertexStride; - } - - public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase) - { - _numTriangles = triangleIndexBase.Length; - _triangleIndexBase = triangleIndexBase; - _triangleIndexStride = 32; - _vertexBase = vertexBase; - _numVertices = vertexBase.Length; - _vertexStride = 24; - } - - public int TriangleCount - { - get { return _numTriangles; } - set { _numTriangles = value; } - } - - public int[] TriangleIndexBase - { - get { return _triangleIndexBase; } - set { _triangleIndexBase = value; } - } - - public int TriangleIndexStride - { - get { return _triangleIndexStride; } - set { _triangleIndexStride = value; } - } - - public int VertexCount - { - get { return _numVertices; } - set { _numVertices = value; } - } - - public Vector3[] VertexBase - { - get { return _vertexBase; } - set { _vertexBase = value; } - } - - public int VertexStride - { - get { return _vertexStride; } - set { _vertexStride = value; } - } - } - - /// - /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. - /// Additional meshes can be added using addIndexedMesh - /// - public class TriangleIndexVertexArray : StridingMeshInterface - { - private List _indexedMeshes = new List(); - - public TriangleIndexVertexArray() - { - } - - public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, - int numVertices, Vector3[] vertexBase, int vertexStride) - { - IndexedMesh mesh = new IndexedMesh(); - mesh.TriangleCount = numTriangleIndices; - mesh.TriangleIndexBase = triangleIndexBase; - mesh.TriangleIndexStride = triangleIndexStride; - mesh.VertexBase = vertexBase; - mesh.VertexCount = numVertices; - mesh.VertexStride = vertexStride; - - AddIndexedMesh(mesh); - } - - public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase) - : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) - { - } - - public void AddIndexedMesh(IndexedMesh indexedMesh) - { - _indexedMeshes.Add(indexedMesh); - } - - public override void GetLockedVertexIndexBase(out List verts, out List indicies, out int numfaces, - int subpart) - { - throw new Exception("The method or operation is not implemented."); - } - - public override void GetLockedReadOnlyVertexIndexBase(out List verts, out List indicies, - out int numfaces, int subpart) - { - IndexedMesh m = _indexedMeshes[0]; - Vector3[] vertexBase = m.VertexBase; - verts = new List(); - foreach (Vector3 v in vertexBase) - { - verts.Add(v); - } - int[] indexBase = m.TriangleIndexBase; - indicies = new List(); - foreach (int i in indexBase) - { - indicies.Add(i); - } - numfaces = vertexBase.GetLength(0); - } - - public override void UnLockVertexBase(int subpart) - { - throw new Exception("The method or operation is not implemented."); - } - - public override void UnLockReadOnlyVertexBase(int subpart) - { - } - - public override int SubPartsCount() - { - return _indexedMeshes.Count; - } - - public override void PreallocateVertices(int numverts) - { - throw new Exception("The method or operation is not implemented."); - } - - public override void PreallocateIndices(int numindices) - { - throw new Exception("The method or operation is not implemented."); - } - } -} diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c36d2a4..0ef6880 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -149,14 +149,11 @@ ;; Choose one of the physics engines below ;; OpenDynamicsEngine is by some distance the most developed physics engine - ;; basicphysics effectively does not model physics at all, making all - ;; objects phantom - ;; The Bullet plugins do not work properly right now. A better Bullet plugin is on the way. + ;; basicphysics effectively does not model physics at all, making all objects phantom ;; Default is OpenDynamicsEngine ; physics = OpenDynamicsEngine ; physics = basicphysics ; physics = POS - ; physics = modified_BulletX ;# {permissionmodules} {} {Permission modules to use (may specify multiple modules, separated by space} {} DefaultPermissionsModule ;; Permission modules to use, separated by space. diff --git a/prebuild.xml b/prebuild.xml index 3aca02d..690de5a 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -573,34 +573,6 @@ - - - - ../../../../bin/Physics/ - - - - - ../../../../bin/Physics/ - - - - ../../../../bin/ - - - - - - - - - - - - - - - @@ -690,34 +662,6 @@ - - - - ../../../../bin/Physics/ - - - - - ../../../../bin/Physics/ - - - - ../../../../bin/ - - - - - - - - - - - - - - - -- cgit v1.1 From 27af016381f2f4aaa8cda99ce7f029980bf8ea76 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 17 Sep 2011 01:13:07 +0100 Subject: Add BulletSim physics option details to OpenSim.ini.example. Marked as in development and experimental. --- bin/OpenSim.ini.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 0ef6880..925c343 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -149,9 +149,11 @@ ;; Choose one of the physics engines below ;; OpenDynamicsEngine is by some distance the most developed physics engine + ;; BulletSim is incomplete and experimental but in active development ;; basicphysics effectively does not model physics at all, making all objects phantom ;; Default is OpenDynamicsEngine ; physics = OpenDynamicsEngine + ; physics = BulletSim ; physics = basicphysics ; physics = POS -- cgit v1.1 From 1e798136c3458b8255fcb6341713bf9dbb689f4b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 17 Sep 2011 01:33:55 +0100 Subject: adjust some whitespace to trigger another build, to check the last failure was just a glitch --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 924d7c2..ac92b8b 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -1526,6 +1526,7 @@ Console.WriteLine("changeadd 1"); { if (Body == IntPtr.Zero) enableBody(); + //Prim auto disable after 20 frames, //if you move it, re-enable the prim manually. if (_parent != null) @@ -1536,6 +1537,7 @@ Console.WriteLine("changeadd 1"); m_linkJoint = IntPtr.Zero; } } + if (Body != IntPtr.Zero) { d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); @@ -1599,7 +1601,6 @@ Console.WriteLine(" JointCreateFixed"); float fy = 0; float fz = 0; - if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. { if (m_vehicle.Type != Vehicle.TYPE_NONE) @@ -1818,7 +1819,6 @@ Console.WriteLine(" JointCreateFixed"); // 35x10 = 350n times the mass per second applied maximum. float nmax = 35f * m_mass; float nmin = -35f * m_mass; - if (fx > nmax) fx = nmax; -- cgit v1.1 From aadf7dd91cdeb98b48cd81c5db06481593aff993 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 20 Sep 2011 20:56:32 +0100 Subject: Remove vestigal OpenSim.Data mono addins extension points that don't look like they've been active for at least 2 and a half years --- .../MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml | 23 ---------------------- .../MySQL/Resources/OpenSim.Data.MySQL.addin.xml | 23 ---------------------- .../SQLite/Resources/OpenSim.Data.SQLite.addin.xml | 20 ------------------- 3 files changed, 66 deletions(-) delete mode 100644 OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml delete mode 100644 OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml delete mode 100644 OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml diff --git a/OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml b/OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml deleted file mode 100644 index 15fd29e..0000000 --- a/OpenSim/Data/MSSQL/Resources/OpenSim.Data.MSSQL.addin.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml b/OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml deleted file mode 100644 index 9e99547..0000000 --- a/OpenSim/Data/MySQL/Resources/OpenSim.Data.MySQL.addin.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml b/OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml deleted file mode 100644 index e6764fa..0000000 --- a/OpenSim/Data/SQLite/Resources/OpenSim.Data.SQLite.addin.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -- cgit v1.1 From fa9291512aabbe72cb6b1b0b7a9af79d9b05d253 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Tue, 20 Sep 2011 14:07:10 -0700 Subject: Make debug statements in ScenePresence consistent and add a few more --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9358a4a..b1094cc 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes { // ~ScenePresence() // { -// m_log.Debug("[ScenePresence] Destructor called"); +// m_log.Debug("[SCENE PRESENCE] Destructor called"); // } private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -517,7 +517,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message); + m_log.Error("[SCENE PRESENCE]: ABSOLUTE POSITION " + e.Message); } } @@ -570,7 +570,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message); + m_log.Error("[SCENE PRESENCE]: VELOCITY " + e.Message); } } @@ -1008,7 +1008,7 @@ namespace OpenSim.Region.Framework.Scenes Animator.ResetAnimations(); // m_log.DebugFormat( -// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", +// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", // Name, UUID, m_scene.RegionInfo.RegionName); // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, @@ -1175,7 +1175,7 @@ namespace OpenSim.Region.Framework.Scenes m_callbackURI = null; } - //m_log.DebugFormat("Completed movement"); + m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); SendInitialData(); @@ -2416,7 +2416,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 pos = m_pos; pos.Z += m_appearance.HipOffset; - //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); + //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); remoteClient.SendPrimUpdate( this, @@ -2503,6 +2503,7 @@ namespace OpenSim.Region.Framework.Scenes ///
private void SendInitialData() { + m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); // Moved this into CompleteMovement to ensure that m_appearance is initialized before // the inventory arrives // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); @@ -2547,10 +2548,11 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendAvatarDataToAllAgents() { + m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); // only send update from root agents to other clients; children are only "listening posts" if (IsChildAgent) { - m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); + m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent"); return; } @@ -2600,7 +2602,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendAvatarDataToAgent(ScenePresence avatar) { -// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); + m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); avatar.ControllingClient.SendAvatarDataImmediate(this); if (Animator != null) @@ -2613,10 +2615,11 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendAppearanceToAllOtherAgents() { + m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} ({1})", Name, UUID); // only send update from root agents to other clients; children are only "listening posts" if (IsChildAgent) { - m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); + m_log.Warn("[SCENE PRESENCE] attempt to send avatar data from a child agent"); return; } @@ -2642,6 +2645,7 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendOtherAgentsAppearanceToMe() { + m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID); m_perfMonMS = Util.EnvironmentTickCount(); int count = 0; @@ -3826,4 +3830,4 @@ namespace OpenSim.Region.Framework.Scenes } } } -} \ No newline at end of file +} -- cgit v1.1 From 7ec7a3cf33b3a67cb10df14bad04cf6f09262822 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Tue, 20 Sep 2011 15:31:43 -0700 Subject: Null simulation data must return a non-null region settings or other parts of the simulator expect --- OpenSim/Data/Null/NullSimulationData.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs index c33a6f2..b788976 100644 --- a/OpenSim/Data/Null/NullSimulationData.cs +++ b/OpenSim/Data/Null/NullSimulationData.cs @@ -77,8 +77,10 @@ namespace OpenSim.Data.Null } public RegionSettings LoadRegionSettings(UUID regionUUID) - { - return null; + { + RegionSettings rs = new RegionSettings(); + rs.RegionUUID = regionUUID; + return rs; } public void StoreObject(SceneObjectGroup obj, UUID regionUUID) -- cgit v1.1 From 8159fd7110459246ff61a41800899f5d854eceee Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 21 Sep 2011 19:28:41 +0100 Subject: When calling osNpcMoveTo(), rotate the avatar in the direction of travel. This stops the npc walking backwards if the target is directly behind. This means that the npc no longer returns to its original rotation once movement has finished. If you want this behaviour, please store and reset the original rotation after movement. This is somewhat to address http://opensimulator.org/mantis/view.php?id=5678 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 23 +++++- .../World/NPC/Tests/NPCModuleTests.cs | 16 +++-- .../Tests/Common/QuaternionToleranceConstraint.cs | 82 ++++++++++++++++++++++ 3 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 OpenSim/Tests/Common/QuaternionToleranceConstraint.cs diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9358a4a..cd3cb60 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -585,7 +585,11 @@ namespace OpenSim.Region.Framework.Scenes public Quaternion Rotation { get { return m_bodyRot; } - set { m_bodyRot = value; } + set + { + m_bodyRot = value; + m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); + } } public Quaternion PreviousRotation @@ -1711,7 +1715,7 @@ namespace OpenSim.Region.Framework.Scenes // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is // always slightly higher than the actual terrain height. - // FIXME: This constrains NOC movements as well, so should be somewhere else. + // FIXME: This constrains NPC movements as well, so should be somewhere else. if (pos.Z - terrainHeight < 0.2) pos.Z = terrainHeight; @@ -1727,6 +1731,21 @@ namespace OpenSim.Region.Framework.Scenes MovingToTarget = true; MoveToPositionTarget = pos; + // Rotate presence around the z-axis to point in same direction as movement. + // Ignore z component of vector + Vector3 localVectorToTarget3D = pos - AbsolutePosition; + Vector3 localVectorToTarget2D = new Vector3((float)(localVectorToTarget3D.X), (float)(localVectorToTarget3D.Y), 0f); + +// m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0}", localVectorToTarget2D); + + // Calculate the yaw. + Vector3 angle = new Vector3(0, 0, (float)(Math.Atan2(localVectorToTarget2D.Y, localVectorToTarget2D.X))); + +// m_log.DebugFormat("[SCENE PRESENCE]: Angle is {0}", angle); + + Rotation = Quaternion.CreateFromEulers(angle); +// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation); + Vector3 agent_control_v3 = new Vector3(); HandleMoveToTargetUpdate(ref agent_control_v3); AddNewMovement(agent_control_v3); diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 246bc34..1a0d0c7 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -182,18 +182,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests scene.Update(); Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - Vector3 targetPos = startPos + new Vector3(0, 0, 10); + Vector3 targetPos = startPos + new Vector3(0, 10, 0); npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false); Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); + //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f))); + Assert.That( + npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001)); scene.Update(); // We should really check the exact figure. Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X)); - Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y)); - Assert.That(npc.AbsolutePosition.Z, Is.GreaterThan(startPos.Z)); - Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.Z)); + Assert.That(npc.AbsolutePosition.Y, Is.GreaterThan(startPos.Y)); + Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); + Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X)); for (int i = 0; i < 10; i++) scene.Update(); @@ -208,6 +211,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests targetPos = startPos + new Vector3(10, 0, 0); npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false); + Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); +// Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0, 1))); + Assert.That( + npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001)); + scene.Update(); // We should really check the exact figure. diff --git a/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs b/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs new file mode 100644 index 0000000..b38c382 --- /dev/null +++ b/OpenSim/Tests/Common/QuaternionToleranceConstraint.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 OpenMetaverse; +using NUnit.Framework; +using NUnit.Framework.Constraints; + +namespace OpenSim.Tests.Common +{ + public class QuaternionToleranceConstraint : ANumericalToleranceConstraint + { + private Quaternion _baseValue; + private Quaternion _valueToBeTested; + + public QuaternionToleranceConstraint(Quaternion baseValue, double tolerance) : base(tolerance) + { + _baseValue = baseValue; + } + + /// + /// Test whether the constraint is satisfied by a given value + /// + /// The value to be tested + /// + /// True for success, false for failure + /// + public override bool Matches(object valueToBeTested) + { + if (valueToBeTested == null) + { + throw new ArgumentException("Constraint cannot be used upon null values."); + } + if (valueToBeTested.GetType() != typeof (Quaternion)) + { + throw new ArgumentException("Constraint cannot be used upon non quaternion values."); + } + + _valueToBeTested = (Quaternion)valueToBeTested; + + return (IsWithinDoubleConstraint(_valueToBeTested.X, _baseValue.X) && + IsWithinDoubleConstraint(_valueToBeTested.Y, _baseValue.Y) && + IsWithinDoubleConstraint(_valueToBeTested.Z, _baseValue.Z) && + IsWithinDoubleConstraint(_valueToBeTested.W, _baseValue.W)); + } + + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WriteExpectedValue( + string.Format("A value {0} within tolerance of plus or minus {1}", _baseValue, _tolerance)); + } + + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(_valueToBeTested); + } + } +} \ No newline at end of file -- cgit v1.1 From 572b680cb01a856f860b1e3fb40a7153a36113f2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 21 Sep 2011 20:15:06 +0100 Subject: get rid of an incredibly noisy logging message from the last commit --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5a3e587..affb844 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -588,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes set { m_bodyRot = value; - m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); +// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); } } -- cgit v1.1 From f9438e7147bbb347a45b14126fa7181307f8ef43 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 21 Sep 2011 22:01:57 +0100 Subject: Remove unused and never set SP.PreviousRotation --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index affb844..82d9abf 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -178,8 +178,6 @@ namespace OpenSim.Region.Framework.Scenes private Quaternion m_bodyRot = Quaternion.Identity; - private Quaternion m_bodyRotPrevious = Quaternion.Identity; - private const int LAND_VELOCITYMAG_MAX = 12; public bool IsRestrictedToRegion; @@ -592,12 +590,6 @@ namespace OpenSim.Region.Framework.Scenes } } - public Quaternion PreviousRotation - { - get { return m_bodyRotPrevious; } - set { m_bodyRotPrevious = value; } - } - /// /// If this is true, agent doesn't have a representation in this scene. /// this is an agent 'looking into' this scene from a nearby scene(region) -- cgit v1.1 From 241e07d006fad1b54e088d8a9ddede0b98a1e800 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 21 Sep 2011 23:56:11 +0100 Subject: Move code which handles NPC movement into Scene so that this can also be used by Autopilot coming from the client side. I thought that I had implemented this but must have accidentally removed it. Adds a regression test to detect if this happens again. Temporarily disables automatic landing of NPC at a target. Will be fixed presently. --- OpenSim/Region/Framework/Scenes/Scene.cs | 67 ++++++++++ .../Scenes/Tests/ScenePresenceAutopilotTests.cs | 135 +++++++++++++++++++++ .../Region/OptionalModules/World/NPC/NPCModule.cs | 2 +- 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 976e001..000a6ed 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -870,6 +870,8 @@ namespace OpenSim.Region.Framework.Scenes if (dm != null) m_eventManager.OnPermissionError += dm.SendAlertToUser; + + m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; } public override string GetSimulatorVersion() @@ -5138,5 +5140,70 @@ namespace OpenSim.Region.Framework.Scenes reason = String.Empty; return true; } + + /// + /// This method deals with movement when an avatar is automatically moving (but this is distinct from the + /// autopilot that moves an avatar to a sit target!. + /// + /// + /// This is not intended as a permament location for this method. + /// + /// + private void HandleOnSignificantClientMovement(ScenePresence presence) + { + if (presence.MovingToTarget) + { + double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget); +// m_log.DebugFormat( +// "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}", +// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget); + + // Check the error term of the current position in relation to the target position + if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT) + { + // We are close enough to the target +// m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name); + + presence.Velocity = Vector3.Zero; + presence.AbsolutePosition = presence.MoveToPositionTarget; + presence.ResetMoveToTarget(); + + if (presence.PhysicsActor.Flying) + { + // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot + // the target if flying. + // We really need to be more subtle (slow the avatar as it approaches the target) or at + // least be able to set collision status once, rather than 5 times to give it enough + // weighting so that that PhysicsActor thinks it really is colliding. + for (int i = 0; i < 5; i++) + presence.PhysicsActor.IsColliding = true; + +// Vector3 targetPos = presence.MoveToPositionTarget; +// if (m_avatars[presence.UUID].LandAtTarget) +// presence.PhysicsActor.Flying = false; + +// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; +// if (targetPos.Z - terrainHeight < 0.2) +// { +// presence.PhysicsActor.Flying = false; +// } + } + +// m_log.DebugFormat( +// "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}", +// presence.AgentControlFlags, presence.MovementFlag, presence.Name); + } + else + { +// m_log.DebugFormat( +// "[SCENE]: Updating npc {0} at {1} for next movement to {2}", +// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); + + Vector3 agent_control_v3 = new Vector3(); + presence.HandleMoveToTargetUpdate(ref agent_control_v3); + presence.AddNewMovement(agent_control_v3); + } + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs new file mode 100644 index 0000000..5a85d7f --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs @@ -0,0 +1,135 @@ +/* + * 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 log4net; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + [TestFixture] + public class ScenePresenceAutopilotTests + { + private TestScene m_scene; + + [TestFixtureSetUp] + public void FixtureInit() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.None; + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten not to worry about such things. + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + + [SetUp] + public void Init() + { + m_scene = SceneHelpers.SetupScene(); + } + + [Test] + public void TestMove() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); + + Vector3 startPos = sp.AbsolutePosition; +// Vector3 startPos = new Vector3(128, 128, 30); + + // For now, we'll make the scene presence fly to simplify this test, but this needs to change. + sp.PhysicsActor.Flying = true; + + m_scene.Update(); + Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); + + Vector3 targetPos = startPos + new Vector3(0, 10, 0); + sp.MoveToTarget(targetPos, false); + + Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); + Assert.That( + sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001)); + + m_scene.Update(); + + // We should really check the exact figure. + Assert.That(sp.AbsolutePosition.X, Is.EqualTo(startPos.X)); + Assert.That(sp.AbsolutePosition.Y, Is.GreaterThan(startPos.Y)); + Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); + Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X)); + + for (int i = 0; i < 10; i++) + m_scene.Update(); + + double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos); + Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move"); + Assert.That(sp.AbsolutePosition, Is.EqualTo(targetPos)); + Assert.That(sp.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE)); + + // Try a second movement + startPos = sp.AbsolutePosition; + targetPos = startPos + new Vector3(10, 0, 0); + sp.MoveToTarget(targetPos, false); + + Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); + Assert.That( + sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001)); + + m_scene.Update(); + + // We should really check the exact figure. + Assert.That(sp.AbsolutePosition.X, Is.GreaterThan(startPos.X)); + Assert.That(sp.AbsolutePosition.X, Is.LessThan(targetPos.X)); + Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y)); + Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); + + for (int i = 0; i < 10; i++) + m_scene.Update(); + + distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos); + Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move"); + Assert.That(sp.AbsolutePosition, Is.EqualTo(targetPos)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index 2fdeeab..6282245 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -53,7 +53,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC if (config != null && config.GetBoolean("Enabled", false)) { scene.RegisterModuleInterface(this); - scene.EventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; +// scene.EventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; } } -- cgit v1.1 From d358125cac4e01194dae4b1f0bc9afc87e463f76 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 22 Sep 2011 00:16:05 +0100 Subject: Reinstate option to land an npc when it reaches a target. This is moved into ScenePresence for now as a general facility --- .../Rest/Inventory/tests/Remote.cs | 2 +- OpenSim/Framework/IClientAPI.cs | 2 +- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 6 +- .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 11 +++- .../Scenes/Tests/ScenePresenceAutopilotTests.cs | 4 +- .../Server/IRCClientView.cs | 2 +- .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 7 +-- .../Region/OptionalModules/World/NPC/NPCModule.cs | 72 +--------------------- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 12 files changed, 28 insertions(+), 90 deletions(-) diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs index 1023108..b53806c 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/tests/Remote.cs @@ -169,7 +169,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory.Tests float y = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Y]); float z = Convert.ToSingle(rdata.Parameters[PARM_MOVE_Z]); Vector3 vector = new Vector3(x, y, z); - presence.MoveToTarget(vector, false); + presence.MoveToTarget(vector, false, false); } catch (Exception e) { diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 150ff1b..47e79d1 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -935,7 +935,7 @@ namespace OpenSim.Framework event ScriptReset OnScriptReset; event GetScriptRunning OnGetScriptRunning; event SetScriptRunning OnSetScriptRunning; - event Action OnAutoPilotGo; + event Action OnAutoPilotGo; event TerrainUnacked OnUnackedTerrain; event ActivateGesture OnActivateGesture; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b5c6742..ce2ff86 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -231,7 +231,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; @@ -11640,9 +11640,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP locy = Convert.ToSingle(args[1]) - (float)regionY; locz = Convert.ToSingle(args[2]); - Action handlerAutoPilotGo = OnAutoPilotGo; + Action handlerAutoPilotGo = OnAutoPilotGo; if (handlerAutoPilotGo != null) - handlerAutoPilotGo(new Vector3(locx, locy, locz), false); + handlerAutoPilotGo(new Vector3(locx, locy, locz), false, false); } /// diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index c87790f..b0266c5 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -222,7 +222,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 000a6ed..eadec09 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5178,10 +5178,10 @@ namespace OpenSim.Region.Framework.Scenes for (int i = 0; i < 5; i++) presence.PhysicsActor.IsColliding = true; -// Vector3 targetPos = presence.MoveToPositionTarget; -// if (m_avatars[presence.UUID].LandAtTarget) -// presence.PhysicsActor.Flying = false; + if (presence.LandAtTarget) + presence.PhysicsActor.Flying = false; +// Vector3 targetPos = presence.MoveToPositionTarget; // float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; // if (targetPos.Z - terrainHeight < 0.2) // { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index e7f2491..980b01f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1599,7 +1599,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); if (avatar != null) { - avatar.MoveToTarget(target, false); + avatar.MoveToTarget(target, false, false); } } else diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 82d9abf..a7b189b 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -220,6 +220,11 @@ namespace OpenSim.Region.Framework.Scenes public bool MovingToTarget { get; private set; } public Vector3 MoveToPositionTarget { get; private set; } + /// + /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying). + /// + public bool LandAtTarget { get; private set; } + private bool m_followCamAuto; private int m_movementUpdateCount; @@ -1681,7 +1686,10 @@ namespace OpenSim.Region.Framework.Scenes /// This is to allow movement to targets that are known to be on an elevated platform with a continuous path /// from start to finish. /// - public void MoveToTarget(Vector3 pos, bool noFly) + /// + /// If true and the avatar starts flying during the move then land at the target. + /// + public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget) { m_log.DebugFormat( "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}", @@ -1720,6 +1728,7 @@ namespace OpenSim.Region.Framework.Scenes else if (pos.Z > terrainHeight) PhysicsActor.Flying = true; + LandAtTarget = landAtTarget; MovingToTarget = true; MoveToPositionTarget = pos; diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs index 5a85d7f..64c36ff 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs @@ -85,7 +85,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); Vector3 targetPos = startPos + new Vector3(0, 10, 0); - sp.MoveToTarget(targetPos, false); + sp.MoveToTarget(targetPos, false, false); Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); Assert.That( @@ -110,7 +110,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Try a second movement startPos = sp.AbsolutePosition; targetPos = startPos + new Vector3(10, 0, 0); - sp.MoveToTarget(targetPos, false); + sp.MoveToTarget(targetPos, false, false); Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); Assert.That( diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index c413634..f6656c2 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -806,7 +806,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; public event ActivateGesture OnActivateGesture; public event DeactivateGesture OnDeactivateGesture; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 31e79fa..edb618e 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -37,11 +37,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC { public class NPCAvatar : IClientAPI { - /// - /// Signal whether the avatar should land when it reaches a move target - /// - public bool LandAtTarget { get; set; } - private readonly string m_firstname; private readonly string m_lastname; private readonly Vector3 m_startPos; @@ -333,7 +328,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index 6282245..bcd9e94 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -53,78 +53,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC if (config != null && config.GetBoolean("Enabled", false)) { scene.RegisterModuleInterface(this); -// scene.EventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; - } - } - - public void HandleOnSignificantClientMovement(ScenePresence presence) - { - lock (m_avatars) - { - if (m_avatars.ContainsKey(presence.UUID) && presence.MovingToTarget) - { - double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget); -// m_log.DebugFormat( -// "[NPC MODULE]: Abs pos of {0} is {1}, target {2}, distance {3}", -// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget); - - // Check the error term of the current position in relation to the target position - if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT) - { - // We are close enough to the target - m_log.DebugFormat("[NPC MODULE]: Stopping movement of npc {0}", presence.Name); - - presence.Velocity = Vector3.Zero; - presence.AbsolutePosition = presence.MoveToPositionTarget; - presence.ResetMoveToTarget(); - - if (presence.PhysicsActor.Flying) - { - // A horrible hack to stop the NPC dead in its tracks rather than having them overshoot - // the target if flying. - // We really need to be more subtle (slow the avatar as it approaches the target) or at - // least be able to set collision status once, rather than 5 times to give it enough - // weighting so that that PhysicsActor thinks it really is colliding. - for (int i = 0; i < 5; i++) - presence.PhysicsActor.IsColliding = true; - -// Vector3 targetPos = presence.MoveToPositionTarget; - if (m_avatars[presence.UUID].LandAtTarget) - presence.PhysicsActor.Flying = false; - -// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y]; -// if (targetPos.Z - terrainHeight < 0.2) -// { -// presence.PhysicsActor.Flying = false; -// } - } - -// m_log.DebugFormat( -// "[NPC MODULE]: AgentControlFlags {0}, MovementFlag {1} for {2}", -// presence.AgentControlFlags, presence.MovementFlag, presence.Name); - } - else - { -// m_log.DebugFormat( -// "[NPC MODULE]: Updating npc {0} at {1} for next movement to {2}", -// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget); - - Vector3 agent_control_v3 = new Vector3(); - presence.HandleMoveToTargetUpdate(ref agent_control_v3); - presence.AddNewMovement(agent_control_v3); - } -// -//// presence.DoMoveToPositionUpdate((0, presence.MoveToPositionTarget, null); - -// -// - - } } } public bool IsNPC(UUID agentId, Scene scene) { + // FIXME: This implementation could not just use the ScenePresence.PresenceType (and callers could inspect + // that directly). ScenePresence sp = scene.GetScenePresence(agentId); if (sp == null || sp.IsChildAgent) return false; @@ -218,8 +153,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); - m_avatars[agentID].LandAtTarget = landAtTarget; - sp.MoveToTarget(pos, noFly); + sp.MoveToTarget(pos, noFly, landAtTarget); return true; } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index b7cefeb..71f2bf4 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -234,7 +234,7 @@ namespace OpenSim.Tests.Common.Mock public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; + public event Action OnAutoPilotGo; public event TerrainUnacked OnUnackedTerrain; -- cgit v1.1 From 2c0bb8118db0b91c14783c2e2a401725e88aa650 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 21 Sep 2011 16:24:19 -0700 Subject: Commented out new debug statements in ScenePresence --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 82d9abf..b1c2eea 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1171,7 +1171,7 @@ namespace OpenSim.Region.Framework.Scenes m_callbackURI = null; } - m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); + //m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); SendInitialData(); @@ -2514,7 +2514,7 @@ namespace OpenSim.Region.Framework.Scenes /// private void SendInitialData() { - m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); + //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); // Moved this into CompleteMovement to ensure that m_appearance is initialized before // the inventory arrives // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); @@ -2559,7 +2559,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendAvatarDataToAllAgents() { - m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); + //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); // only send update from root agents to other clients; children are only "listening posts" if (IsChildAgent) { @@ -2613,7 +2613,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendAvatarDataToAgent(ScenePresence avatar) { - m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); + //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); avatar.ControllingClient.SendAvatarDataImmediate(this); if (Animator != null) @@ -2656,7 +2656,7 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendOtherAgentsAppearanceToMe() { - m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID); + //m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID); m_perfMonMS = Util.EnvironmentTickCount(); int count = 0; -- cgit v1.1 From 3ccb58c05c0a11fb4cff0f3adf90ca29d67b0c8b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 22 Sep 2011 01:08:38 +0100 Subject: Fix failure to teleport when an agent is lured on the same sim (and probably in neighbouring sims) with HG lure active It turns out that the HG lure module was setting up a pending lure when it intercepted the instant message on its way out to the target avatar. However, an IM would only be sent if the user was remote, so it would not be set up for users on the same sim or in an immediate neighbour. We fix this by adding the pending lure when the message goes out and ignoring a duplicate pending lure add if it goes to out via IM. Hopefully addresses http://opensimulator.org/mantis/view.php?id=5690 --- .../Avatar/InstantMessage/HGMessageTransferModule.cs | 11 ++++++----- OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index 7753c25..d294692 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -24,6 +24,7 @@ * (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; @@ -145,14 +146,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage scene.Entities[toAgentID] is ScenePresence) { // m_log.DebugFormat( -// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", +// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; if (!user.IsChildAgent) { // Local message -// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); +// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); user.ControllingClient.SendInstantMessage(im); // Message sent @@ -166,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( -// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); +// "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) @@ -174,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; -// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); +// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); user.ControllingClient.SendInstantMessage(im); // Message sent @@ -183,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } } -// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); +// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); // Is the user a local user? UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); string url = string.Empty; diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index d687e6a..bc5c1ff 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -154,14 +154,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) { UUID sessionID = new UUID(im.imSessionID); - m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); - m_PendingLures.Add(sessionID, im, 7200); // 2 hours + + if (!m_PendingLures.Contains(sessionID)) + { + m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); + m_PendingLures.Add(sessionID, im, 7200); // 2 hours + } // Forward. We do this, because the IM module explicitly rejects // IMs of this type if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); - } } @@ -177,12 +180,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); + UUID sessionID = UUID.Random(); + GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, - message, UUID.Random(), false, presence.AbsolutePosition, + message, sessionID, false, presence.AbsolutePosition, new Byte[0]); m.RegionID = client.Scene.RegionInfo.RegionID.Guid; + + m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); + m_PendingLures.Add(sessionID, m, 7200); // 2 hours if (m_TransferModule != null) { -- cgit v1.1 From c8304b7f84b1a8d9fb978cae510f684e36419deb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Sep 2011 02:59:33 +0100 Subject: Fix avatar parameter updating for viewer 3 and maybe 2. When a slider parameter is changed, the viewer uploads a new shape (or other asset) and the item is updated to point to it. Viewer 1 uploaded the data in the initial request itself, so the asset references was almost always correctly updated. However, viewer 3/2 always uploads data in a subsequent xfer, which exposed a race condition where the viewer would make the item update before the asset had uploaded. This commit shuffles the order of operations to avoid this race, the item is updated with the new asset id instead of the old one while the upload was still taking place. A second race had to be fixed where avatar appearance would also be updated with the old asset id rather than the new one. This was fixed by updating the avatar appearance ids when the appearance was actually saved, rather than when the wearables update was made. --- OpenSim/Framework/AssetBase.cs | 1 + OpenSim/Framework/AvatarAppearance.cs | 2 + .../AssetTransaction/AgentAssetsTransactions.cs | 168 +++++++++++++++------ .../AssetTransaction/AssetTransactionModule.cs | 25 ++- .../Agent/AssetTransaction/AssetXferUploader.cs | 127 +++++++++++++--- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 19 ++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 7 +- .../Services/InventoryService/XInventoryService.cs | 14 +- 8 files changed, 270 insertions(+), 93 deletions(-) diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs index e8c85c9..d2c6c57 100644 --- a/OpenSim/Framework/AssetBase.cs +++ b/OpenSim/Framework/AssetBase.cs @@ -167,6 +167,7 @@ namespace OpenSim.Framework get { return m_metadata.FullID; } set { m_metadata.FullID = value; } } + /// /// Asset MetaData ID (transferring from UUID to string ID) /// diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index c69dde3..72b580b 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -225,6 +225,8 @@ namespace OpenSim.Framework ///
public virtual void ResetAppearance() { +// m_log.WarnFormat("[AVATAR APPEARANCE]: Reset appearance"); + m_serial = 0; SetDefaultTexture(); diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 9d8082b..eed7cd5 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -41,14 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ///
public class AgentAssetTransactions { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // Fields private bool m_dumpAssetsToFile; private Scene m_Scene; - public UUID UserID; - public Dictionary XferUploaders = - new Dictionary(); + private UUID UserID; + private Dictionary XferUploaders = new Dictionary(); // Methods public AgentAssetTransactions(UUID agentID, Scene scene, @@ -59,36 +58,94 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_dumpAssetsToFile = dumpAssetsToFile; } - public AssetXferUploader RequestXferUploader(UUID transactionID) + /// + /// Return a xfer uploader if one does not already exist. + /// + /// + /// + /// We must transfer the new asset ID into the uploader on creation, otherwise + /// we can see race conditions with other threads which can retrieve an item before it is updated with the new + /// asset id. + /// + /// + /// The xfer uploader requested. Null if one is already in existence. + /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple + /// transfers are made. Needs to be corrected. + /// + public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) { - if (!XferUploaders.ContainsKey(transactionID)) + lock (XferUploaders) { - AssetXferUploader uploader = new AssetXferUploader(m_Scene, - m_dumpAssetsToFile); - - lock (XferUploaders) + if (!XferUploaders.ContainsKey(transactionID)) { + AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); + +// m_log.DebugFormat( +// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); + XferUploaders.Add(transactionID, uploader); - } - return uploader; + return uploader; + } } + + m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); + return null; } public void HandleXfer(ulong xferID, uint packetID, byte[] data) { + AssetXferUploader foundUploader = null; + lock (XferUploaders) { foreach (AssetXferUploader uploader in XferUploaders.Values) { +// m_log.DebugFormat( +// "[AGENT ASSETS TRANSACTIONS]: In HandleXfer, inspect xfer upload with xfer id {0}", +// uploader.XferID); + if (uploader.XferID == xferID) { - uploader.HandleXferPacket(xferID, packetID, data); + foundUploader = uploader; break; } } } + + if (foundUploader != null) + { +// m_log.DebugFormat( +// "[AGENT ASSETS TRANSACTIONS]: Found xfer uploader for xfer id {0}, packet id {1}, data length {2}", +// xferID, packetID, data.Length); + + foundUploader.HandleXferPacket(xferID, packetID, data); + } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", + xferID, packetID, data.Length); + } + } + + public bool RemoveXferUploader(UUID transactionID) + { + lock (XferUploaders) + { + bool removed = XferUploaders.Remove(transactionID); + + if (!removed) + m_log.WarnFormat( + "[AGENT ASSET TRANSACTIONS]: Received request to remove xfer uploader with transaction ID {0} but none found", + transactionID); +// else +// m_log.DebugFormat( +// "[AGENT ASSET TRANSACTIONS]: Removed xfer uploader with transaction ID {0}", transactionID); + + return removed; + } } public void RequestCreateInventoryItem(IClientAPI remoteClient, @@ -96,16 +153,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - if (XferUploaders.ContainsKey(transactionID)) + AssetXferUploader uploader = null; + + lock (XferUploaders) { - XferUploaders[transactionID].RequestCreateInventoryItem( - remoteClient, transactionID, folderID, - callbackID, description, name, invType, type, - wearableType, nextOwnerMask); + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; } - } - + if (uploader != null) + uploader.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); + else + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}", + transactionID, name, remoteClient.Name); + } /// /// Get an uploaded asset. If the data is successfully retrieved, @@ -113,19 +178,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// /// /// The asset if the upload has completed, null if it has not. - public AssetBase GetTransactionAsset(UUID transactionID) + private AssetBase GetTransactionAsset(UUID transactionID) { - if (XferUploaders.ContainsKey(transactionID)) + lock (XferUploaders) { - AssetXferUploader uploader = XferUploaders[transactionID]; - AssetBase asset = uploader.GetAssetData(); - - lock (XferUploaders) + if (XferUploaders.ContainsKey(transactionID)) { - XferUploaders.Remove(transactionID); - } + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + RemoveXferUploader(transactionID); - return asset; + return asset; + } } return null; @@ -135,7 +199,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - if (XferUploaders.ContainsKey(transactionID)) + AssetXferUploader uploader = null; + + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } + + if (uploader != null) { AssetBase asset = GetTransactionAsset(transactionID); @@ -161,28 +233,34 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_Scene.AssetService.Store(asset); } } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", + transactionID, item.Name, part.Name); + } } public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { - if (XferUploaders.ContainsKey(transactionID)) - { - AssetBase asset = GetTransactionAsset(transactionID); + AssetXferUploader uploader = null; - if (asset != null) - { - asset.FullID = UUID.Random(); - asset.Name = item.Name; - asset.Description = item.Description; - asset.Type = (sbyte)item.AssetType; - item.AssetID = asset.FullID; - - m_Scene.AssetService.Store(asset); + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } - IInventoryService invService = m_Scene.InventoryService; - invService.UpdateItem(item); - } + if (uploader != null) + { + uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", + transactionID, item.Name, remoteClient.Name); } } } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 82558de..a28d5d7 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -172,11 +172,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// /// Update an inventory item with data that has been received through a /// transaction. - /// + /// + /// /// This is called when clothing or body parts are updated (for /// instance, with new textures or colours). It may also be called in /// other situations. - ///
+ /// /// /// /// @@ -184,14 +185,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction UUID transactionID, InventoryItemBase item) { // m_log.DebugFormat( -// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", +// "[ASSET TRANSACTION MODULE]: Called HandleItemUpdateFromTransaction with item {0}", // item.Name); - AgentAssetTransactions transactions = - GetUserTransactions(remoteClient.AgentId); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - transactions.RequestUpdateInventoryItem(remoteClient, - transactionID, item); + transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); } /// @@ -255,11 +254,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } - AgentAssetTransactions transactions = - GetUserTransactions(remoteClient.AgentId); - - AssetXferUploader uploader = - transactions.RequestXferUploader(transaction); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); if (uploader != null) { @@ -279,9 +275,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) { - //m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data!"); - AgentAssetTransactions transactions = - GetUserTransactions(remoteClient.AgentId); +// m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data length " + data.Length); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); transactions.HandleXfer(xferID, packetID, data); } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index a7929ba..ec4dfd0 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -40,11 +40,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we + /// are performing a delayed update. + /// + AgentAssetTransactions m_transactions; + private AssetBase m_asset; private UUID InventFolder = UUID.Zero; private sbyte invType = 0; + private bool m_createItem = false; private uint m_createItemCallback = 0; + private bool m_updateItem = false; + private InventoryItemBase m_updateItemData; + private string m_description = String.Empty; private bool m_dumpAssetToFile; private bool m_finished = false; @@ -58,9 +68,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction public ulong XferID; private Scene m_Scene; - public AssetXferUploader(Scene scene, bool dumpAssetToFile) + public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) { + m_transactions = transactions; m_Scene = scene; + m_asset = new AssetBase() { FullID = assetID }; m_dumpAssetToFile = dumpAssetToFile; } @@ -73,6 +85,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// True if the transfer is complete, false otherwise or if the xferID was not valid public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) { +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})", +// packetID, xferID, data.Length); + if (XferID == xferID) { if (m_asset.Data.Length > 1) @@ -107,16 +123,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// /// /// - /// True if the transfer is complete, false otherwise - public bool Initialise(IClientAPI remoteClient, UUID assetID, + public void Initialise(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal, bool tempFile) { +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", +// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); + ourClient = remoteClient; - m_asset = new AssetBase(assetID, "blank", type, - remoteClient.AgentId.ToString()); - m_asset.Data = data; + m_asset.Name = "blank"; m_asset.Description = "empty"; + m_asset.Type = type; + m_asset.CreatorID = remoteClient.AgentId.ToString(); + m_asset.Data = data; m_asset.Local = storeLocal; m_asset.Temporary = tempFile; @@ -126,21 +146,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_asset.Data.Length > 2) { SendCompleteMessage(); - return true; } else { RequestStartXfer(); } - - return false; } protected void RequestStartXfer() { XferID = Util.GetNextXferID(); - ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, - 0, new byte[0]); + +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}", +// m_asset.FullID, m_asset.Type, XferID, ourClient.Name); + + ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]); } protected void SendCompleteMessage() @@ -148,18 +169,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); - m_finished = true; - if (m_createItem) - { - DoCreateItem(m_createItemCallback); - } - else if (m_storeLocal) + // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create + // message from other client UDP. + lock (this) { - m_Scene.AssetService.Store(m_asset); + m_finished = true; + if (m_createItem) + { + DoCreateItem(m_createItemCallback); + } + else if (m_updateItem) + { + StoreAssetForItemUpdate(m_updateItemData); + + // Remove ourselves from the list of transactions if completion was delayed until the transaction + // was complete. + // TODO: Should probably do the same for create item. + m_transactions.RemoveXferUploader(TransactionID); + } + else if (m_storeLocal) + { + m_Scene.AssetService.Store(m_asset); + } } m_log.DebugFormat( - "[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", + "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", m_asset.FullID, TransactionID); if (m_dumpAssetToFile) @@ -205,18 +240,66 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_asset.Description = description; m_asset.Type = type; + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) + { + if (m_finished) + { + DoCreateItem(callbackID); + } + else + { + m_createItem = true; //set flag so the inventory item is created when upload is complete + m_createItemCallback = callbackID; + } + } + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) + { + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) + { + m_asset.Name = item.Name; + m_asset.Description = item.Description; + m_asset.Type = (sbyte)item.AssetType; + + // We must always store the item at this point even if the asset hasn't finished uploading, in order + // to avoid a race condition when the appearance module retrieves the item to set the asset id in + // the AvatarAppearance structure. + item.AssetID = m_asset.FullID; + m_Scene.InventoryService.UpdateItem(item); + if (m_finished) { - DoCreateItem(callbackID); + StoreAssetForItemUpdate(item); } else { - m_createItem = true; //set flag so the inventory item is created when upload is complete - m_createItemCallback = callbackID; +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}", +// item.Name, remoteClient.Name, transactionID); + + m_updateItem = true; + m_updateItemData = item; } } } + /// + /// Store the asset for the given item. + /// + /// + private void StoreAssetForItemUpdate(InventoryItemBase item) + { +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", +// m_asset.FullID, item.Name, ourClient.Name); + + m_Scene.AssetService.Store(m_asset); + } + private void DoCreateItem(uint callbackID) { m_Scene.AssetService.Store(m_asset); diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index bb63bcd..0cadd83 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -211,6 +211,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Process the visual params, this may change height as well if (visualParams != null) { +// string[] visualParamsStrings = new string[visualParams.Length]; +// for (int i = 0; i < visualParams.Length; i++) +// visualParamsStrings[i] = visualParams[i].ToString(); +// m_log.DebugFormat( +// "[AVFACTORY]: Setting visual params for {0} to {1}", +// client.Name, string.Join(", ", visualParamsStrings)); + float oldHeight = sp.Appearance.AvatarHeight; changed = sp.Appearance.SetVisualParams(visualParams); @@ -418,6 +425,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); + // This could take awhile since it needs to pull inventory + // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape + // assets and item asset id changes to complete. + // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids + // multiple save requests. + SetAppearanceAssets(sp.UUID, sp.Appearance); + m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); } @@ -504,9 +518,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory avatAppearance.GetAssetsFrom(sp.Appearance); - // This could take awhile since it needs to pull inventory - SetAppearanceAssets(sp.UUID, ref avatAppearance); - lock (m_setAppearanceLock) { // Update only those fields that we have changed. This is important because the viewer @@ -540,7 +551,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return true; } - private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) + private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) { IInventoryService invService = m_scene.InventoryService; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index f9dba2d..663aa22 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -334,6 +334,10 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, UUID itemID, InventoryItemBase itemUpd) { +// m_log.DebugFormat( +// "[USER INVENTORY]: Updating asset for item {0} {1}, transaction ID {2} for {3}", +// itemID, itemUpd.Name, transactionID, remoteClient.Name); + // This one will let people set next perms on items in agent // inventory. Rut-Roh. Whatever. Make this secure. Yeah. // @@ -385,8 +389,7 @@ namespace OpenSim.Region.Framework.Scenes IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); if (agentTransactions != null) { - agentTransactions.HandleItemUpdateFromTransaction( - remoteClient, transactionID, item); + agentTransactions.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); } } } diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index eeab67a..1648b51 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { - //private static readonly ILog m_log = - // LogManager.GetLogger( - // MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -385,18 +385,22 @@ namespace OpenSim.Services.InventoryService public virtual bool AddItem(InventoryItemBase item) { - //m_log.DebugFormat( - // "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); +// m_log.DebugFormat( +// "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); return m_Database.StoreItem(ConvertFromOpenSim(item)); } public virtual bool UpdateItem(InventoryItemBase item) { +// throw new Exception("urrgh"); if (!m_AllowDelete) if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder) return false; +// m_log.InfoFormat( +// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder); + return m_Database.StoreItem(ConvertFromOpenSim(item)); } -- cgit v1.1 From ceb09cde4ddaff6b7e76ce18656f0c2049bcb8ec Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Sep 2011 21:57:52 +0100 Subject: Correct asset id of library default iris texture. For this change to show up you will need to clear viewer cache. --- bin/inventory/TexturesLibrary/TexturesLibraryItems.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml b/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml index e1452f6..9b5080d 100644 --- a/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml +++ b/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml @@ -564,7 +564,7 @@
- + -- cgit v1.1 From bec0cbe82b0de1b5fa8e214a0cc59d0db1f25959 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Sep 2011 22:20:15 +0100 Subject: remove unused SOP.Create() method --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 7203663..632ac8f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1714,20 +1714,6 @@ namespace OpenSim.Region.Framework.Scenes Name, LocalId, id); } - public static SceneObjectPart Create() - { - SceneObjectPart part = new SceneObjectPart(); - part.UUID = UUID.Random(); - - PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); - part.Shape = shape; - - part.Name = "Primitive"; - part._ownerID = UUID.Random(); - - return part; - } - /// /// Do a physics property update for a NINJA joint. /// -- cgit v1.1