From b341bc090833695184276c48dd36cd946791a00c Mon Sep 17 00:00:00 2001 From: BlueWall Date: Thu, 13 Jan 2011 11:39:50 -0500 Subject: [PATCH 01/45] Make FireAndForgetWrapper a singleton class Made FireAndForgetWrapper a singleton class to allow us to drop dependancy on the BclExtras35 library. BclExtras is broken in Mono 2.8.2 and we used the library in only one function. --- OpenSim/Framework/Util.cs | 27 ++++++++++++++++++++++++--- bin/BclExtras35.dll | Bin 153600 -> 0 bytes prebuild.xml | 2 -- 3 files changed, 24 insertions(+), 5 deletions(-) delete mode 100644 bin/BclExtras35.dll diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 8d1671a885..d1d8736062 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -46,7 +46,7 @@ using System.Threading; using log4net; using Nini.Config; using Nwc.XmlRpc; -using BclExtras; +// using BclExtras; using OpenMetaverse; using OpenMetaverse.StructuredData; using Amib.Threading; @@ -1375,8 +1375,29 @@ namespace OpenSim.Framework /// /// Created to work around a limitation in Mono with nested delegates /// - private class FireAndForgetWrapper + private sealed class FireAndForgetWrapper { + private static volatile FireAndForgetWrapper instance; + private static object syncRoot = new Object(); + + public static FireAndForgetWrapper Instance { + get { + + if (instance == null) + { + lock (syncRoot) + { + if (instance == null) + { + instance = new FireAndForgetWrapper(); + } + } + } + + return instance; + } + } + public void FireAndForget(System.Threading.WaitCallback callback) { callback.BeginInvoke(null, EndFireAndForget, callback); @@ -1445,7 +1466,7 @@ namespace OpenSim.Framework ThreadPool.QueueUserWorkItem(callback, obj); break; case FireAndForgetMethod.BeginInvoke: - FireAndForgetWrapper wrapper = Singleton.GetInstance(); + FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance; wrapper.FireAndForget(callback, obj); break; case FireAndForgetMethod.SmartThreadPool: diff --git a/bin/BclExtras35.dll b/bin/BclExtras35.dll deleted file mode 100644 index 7a7480a3a174bb26fadd394ba7b8566d61cda0ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153600 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 - @@ -1597,7 +1596,6 @@ - From b492f1ce99d27bcf29eb5805564c8778aa4df748 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sat, 12 Feb 2011 20:50:24 -0500 Subject: [PATCH 02/45] Fix unsitting of avatar on linked sets --- 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 cd70de8440..cb2543f03d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -472,7 +472,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); if (part != null) { - return m_parentPosition + (m_pos * part.GetWorldRotation()); + return m_parentPosition + (m_pos * part.RotationOffset); } else { From 0d495ced4c4077ab456119650693c979eeb9d1ea Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 13 Feb 2011 00:29:06 -0500 Subject: [PATCH 03/45] Revert "Fix unsitting of avatar on linked sets" This reverts commit b492f1ce99d27bcf29eb5805564c8778aa4df748. --- 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 cb2543f03d..cd70de8440 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -472,7 +472,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); if (part != null) { - return m_parentPosition + (m_pos * part.RotationOffset); + return m_parentPosition + (m_pos * part.GetWorldRotation()); } else { From 6601771f812a360e6bc949da242878980ac0dd72 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 13 Feb 2011 00:30:43 -0500 Subject: [PATCH 04/45] Set filter to send proper rotations for root part This allows the root prim, alone or in a set, to send it's rotation. This fixes unsitting the avatar on sit-offsest type teleports where the sit target is in the root prim of a linkset. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 6a92378ea7..4d5eedfc95 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2099,7 +2099,7 @@ namespace OpenSim.Region.Framework.Scenes { Quaternion newRot; - if (this.LinkNum == 0) + if (this.LinkNum == 0 || this.LinkNum == 1) { newRot = RotationOffset; } From 98d7de22dc44ca1e5971301c02a6a1fe49620889 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 18:31:41 +0100 Subject: [PATCH 05/45] Fix (add) ability to rez objects by dragging them out of another prim's inventory. This should happen if the client supplies a task ID with the RezObject call. The rez goes through the same code as llRezObject(), so the same perms are applied. Rotation isn't yet preserved, this should be fixed shortly. --- .../InventoryAccess/InventoryAccessModule.cs | 4 ++ .../Framework/Scenes/Scene.Inventory.cs | 59 +++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 9fbfc3477f..cdee53c4e2 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -552,8 +552,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess ///

/// Rez an object into the scene from the user's inventory /// + /// /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. + /// /// /// /// @@ -570,6 +572,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { +// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); + // Work out position details byte bRayEndIsIntersection = (byte)0; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 73dd531536..43708500fe 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1955,11 +1955,60 @@ namespace OpenSim.Region.Framework.Scenes UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID) { - IInventoryAccessModule invAccess = RequestModuleInterface(); - if (invAccess != null) - invAccess.RezObject( - remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, - RezSelected, RemoveItem, fromTaskID, false); +// m_log.DebugFormat( +// "[PRIM INVENTORY]: RezObject from {0} for item {1} from task id {2}", +// remoteClient.Name, itemID, fromTaskID); + + if (fromTaskID == UUID.Zero) + { + IInventoryAccessModule invAccess = RequestModuleInterface(); + if (invAccess != null) + invAccess.RezObject( + remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, + RezSelected, RemoveItem, fromTaskID, false); + } + else + { + SceneObjectPart part = GetSceneObjectPart(fromTaskID); + if (part == null) + { + m_log.ErrorFormat( + "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such scene object", + remoteClient.Name, itemID, fromTaskID); + + return; + } + + TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID); + if (item == null) + { + m_log.ErrorFormat( + "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such item", + remoteClient.Name, itemID, fromTaskID); + + return; + } + + // Work out position details + byte bRayEndIsIntersection = (byte)0; + + if (RayEndIsIntersection) + { + bRayEndIsIntersection = (byte)1; + } + else + { + bRayEndIsIntersection = (byte)0; + } + + Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); + Vector3 pos + = GetNewRezLocation( + RayStart, RayEnd, RayTargetID, Quaternion.Identity, + BypassRayCast, bRayEndIsIntersection, true, scale, false); + + RezObject(part, item, pos, Quaternion.Identity, Vector3.Zero, 0); + } } /// From 3ba5eeb6c3b7c6381ca1e0ed87bce44049f96e37 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 22:15:40 +0100 Subject: [PATCH 06/45] Allow a null rotation to be passed in to RezObject so that we can control whether to use the serialized rotation or not. Not used yet. --- .../Framework/Scenes/Scene.Inventory.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 43708500fe..87b4cb8741 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2016,14 +2016,14 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - /// - /// - /// + /// The position of the rezzed object. + /// The rotation of the rezzed object. If null, then the rotation stored with the object + /// will be used if it exists. + /// The velocity of the rezzed object. /// /// The SceneObjectGroup rezzed or null if rez was unsuccessful public virtual SceneObjectGroup RezObject( - SceneObjectPart sourcePart, TaskInventoryItem item, - Vector3 pos, Quaternion rot, Vector3 vel, int param) + SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) { if (null == item) return null; @@ -2041,8 +2041,14 @@ namespace OpenSim.Region.Framework.Scenes if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) sourcePart.Inventory.RemoveInventoryItem(item.ItemID); } - - AddNewSceneObject(group, true, pos, rot, vel); + + AddNewSceneObject(group, true); + + group.AbsolutePosition = pos; + group.Velocity = vel; + + if (rot != null) + group.UpdateGroupRotationR((Quaternion)rot); // We can only call this after adding the scene object, since the scene object references the scene // to find out if scripts should be activated at all. From 8e0d2cc43b63046b0dd6b9a3a7dafd70a70362d0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 22:21:46 +0100 Subject: [PATCH 07/45] If an object is rezzed directly from a prim inventory then give it the rotation it was stored with. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 87b4cb8741..254879b937 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2007,7 +2007,7 @@ namespace OpenSim.Region.Framework.Scenes RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); - RezObject(part, item, pos, Quaternion.Identity, Vector3.Zero, 0); + RezObject(part, item, pos, null, Vector3.Zero, 0); } } From b0889ed92a3c7d152f9b05aec1ce00dfc010e34e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 22:30:43 +0100 Subject: [PATCH 08/45] refactor: simplify bRayEndIsIntersection boolean set from RayEndIsIntersection byte --- .../InventoryAccess/InventoryAccessModule.cs | 15 +-------------- .../Region/Framework/Scenes/Scene.Inventory.cs | 13 +------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index cdee53c4e2..73b0a35b7c 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -574,21 +574,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); - // Work out position details - byte bRayEndIsIntersection = (byte)0; - - if (RayEndIsIntersection) - { - bRayEndIsIntersection = (byte)1; - } - else - { - bRayEndIsIntersection = (byte)0; - } - + byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); - - Vector3 pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 254879b937..0f85925c78 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1989,18 +1989,7 @@ namespace OpenSim.Region.Framework.Scenes return; } - // Work out position details - byte bRayEndIsIntersection = (byte)0; - - if (RayEndIsIntersection) - { - bRayEndIsIntersection = (byte)1; - } - else - { - bRayEndIsIntersection = (byte)0; - } - + byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = GetNewRezLocation( From da4a9653a27cbb1ecc779774a3d8715afb079086 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 22:33:06 +0100 Subject: [PATCH 09/45] minor: remove some mono compiler warnings --- OpenSim/Data/Null/NullEstateData.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Data/Null/NullEstateData.cs b/OpenSim/Data/Null/NullEstateData.cs index 0cebff55aa..8db8064cbe 100755 --- a/OpenSim/Data/Null/NullEstateData.cs +++ b/OpenSim/Data/Null/NullEstateData.cs @@ -38,9 +38,9 @@ namespace OpenSim.Data.Null { public class NullEstateStore : IEstateDataStore { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private string m_connectionString; +// private string m_connectionString; protected virtual Assembly Assembly { @@ -58,7 +58,7 @@ namespace OpenSim.Data.Null public void Initialise(string connectionString) { - m_connectionString = connectionString; +// m_connectionString = connectionString; } private string[] FieldList From bed463666cdc023bab8db2b725fb85736d2067df Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 23:16:43 +0100 Subject: [PATCH 10/45] minor typo correction. thanks Ai Austin. --- 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 55723d1efb..823daa0cc4 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -16,7 +16,7 @@ ;; files are loaded then type "config show" on the region console command line. ;; ;; -;; NOTES FOR DEVELOPERS REGARDING FORMAT OF TIHS FILE +;; NOTES FOR DEVELOPERS REGARDING THE FORMAT OF THIS FILE ;; ;; All leading white space is ignored, but preserved. ;; From 424995e1384178462799469e0200615308035460 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 12 Apr 2011 23:22:21 +0100 Subject: [PATCH 11/45] Move example HttpProxy setting to OpenSim.ini.example and tidy --- bin/OpenSim.ini.example | 8 ++++++++ bin/OpenSimDefaults.ini | 9 --------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 823daa0cc4..c05c3de2c4 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -201,6 +201,14 @@ ;; If not generating maptiles, use this static texture asset ID ; MaptileStaticUUID = "00000000-0000-0000-0000-000000000000" + ;; Http proxy setting for llHTTPRequest and dynamic texture loading, if required + ; HttpProxy = "http://proxy.com:8080" + + ;; If you're using HttpProxy, then you can set HttpProxyExceptions to a list of regular expressions for URLs that you don't want to go through the proxy + ;; For example, servers inside your firewall. + ;; Separate patterns with a ';' + ; HttpProxyExceptions = ".mydomain.com;localhost" + ;# {emailmodule} {} {Provide llEmail and llGetNextEmail functionality? (requires SMTP server)} {true false} false ;; The email module requires some configuration. It needs an SMTP ;; server to send mail through. diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index d6eee0e101..f857b8da63 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -14,15 +14,6 @@ ; Place to create a PID file ; PIDFile = "/tmp/my.pid" - ; Http proxy support for llHTTPRequest and dynamic texture loading - ; Set HttpProxy to the URL for your proxy server if you would like - ; to proxy llHTTPRequests through a firewall - ; HttpProxy = "http://proxy.com" - ; Set HttpProxyExceptions to a list of regular expressions for - ; URLs that you don't want going through the proxy such as servers - ; inside your firewall, separate patterns with a ';' - ; HttpProxyExceptions = ".mydomain.com;localhost" - startup_console_commands_file = "startup_commands.txt" shutdown_console_commands_file = "shutdown_commands.txt" From 5c870fce548eeca24ae0491a2261ce4fb330a57b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 12 Apr 2011 19:45:33 -0700 Subject: [PATCH 12/45] Bug fix in object serialization -- sculpt data was wrong. --- .../Framework/Scenes/Serialization/SceneObjectSerializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 57ae4fd24f..b412e25579 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1318,7 +1318,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteStartElement("SculptData"); byte[] sd; if (shp.SculptData != null) - sd = shp.ExtraParams; + sd = shp.SculptData; else sd = Utils.EmptyBytes; writer.WriteBase64(sd, 0, sd.Length); From 16c911dcbb883e60d7a49176db8b2cea650cc929 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 12 Apr 2011 19:46:27 -0700 Subject: [PATCH 13/45] Implemented terrain save-tile command. Does the opposite of load-tile. For now, only saves to .png. --- .../FileLoaders/GenericSystemDrawing.cs | 46 ++++++++++++++++ .../World/Terrain/FileLoaders/JPEG.cs | 8 +++ .../World/Terrain/FileLoaders/LLRAW.cs | 8 +++ .../World/Terrain/FileLoaders/RAW32.cs | 7 +++ .../World/Terrain/FileLoaders/Terragen.cs | 8 +++ .../World/Terrain/ITerrainLoader.cs | 1 + .../World/Terrain/TerrainModule.cs | 54 +++++++++++++++++++ 7 files changed, 132 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs index d6fa0937e5..21a9999ba0 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs @@ -124,6 +124,52 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders colours.Save(stream, ImageFormat.Png); } + public virtual void SaveFile(ITerrainChannel m_channel, string filename, + int offsetX, int offsetY, + int fileWidth, int fileHeight, + int regionSizeX, int regionSizeY) + + { + // We need to do this because: + // "Saving the image to the same file it was constructed from is not allowed and throws an exception." + string tempName = offsetX + "_ " + offsetY + "_" + filename; + + Bitmap entireBitmap = null; + Bitmap thisBitmap = null; + if (File.Exists(filename)) + { + File.Copy(filename, tempName); + entireBitmap = new Bitmap(tempName); + if (entireBitmap.Width != fileWidth * regionSizeX || entireBitmap.Height != fileHeight * regionSizeY) + { + // old file, let's overwrite it + entireBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); + } + } + else + { + entireBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); + } + + thisBitmap = CreateGrayscaleBitmapFromMap(m_channel); + Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY); + for (int x = 0; x < regionSizeX; x++) + for (int y = 0; y < regionSizeY; y++) + entireBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y)); + + Save(entireBitmap, filename); + thisBitmap.Dispose(); + entireBitmap.Dispose(); + + if (File.Exists(tempName)) + File.Delete(tempName); + } + + protected virtual void Save(Bitmap bmp, string filename) + { + bmp.Save(filename, ImageFormat.Png); + } + #endregion public override string ToString() diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs index 8667607d0b..1a0d8ecf60 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs @@ -76,6 +76,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders colours.Save(stream, ImageFormat.Jpeg); } + public virtual void SaveFile(ITerrainChannel m_channel, string filename, + int offsetX, int offsetY, + int fileWidth, int fileHeight, + int regionSizeX, int regionSizeY) + { + throw new System.Exception("Not Implemented"); + } + #endregion public override string ToString() diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs index a70ef13ed0..fad7641e42 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs @@ -240,6 +240,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders get { return ".raw"; } } + public virtual void SaveFile(ITerrainChannel m_channel, string filename, + int offsetX, int offsetY, + int fileWidth, int fileHeight, + int regionSizeX, int regionSizeY) + { + throw new System.Exception("Not Implemented"); + } + #endregion public override string ToString() diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs index 3c76665d5e..ba073cae5a 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs @@ -160,6 +160,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders bs.Close(); } + public virtual void SaveFile(ITerrainChannel m_channel, string filename, + int offsetX, int offsetY, + int fileWidth, int fileHeight, + int regionSizeX, int regionSizeY) + { + throw new System.Exception("Not Implemented"); + } #endregion public override string ToString() diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs index 2919897153..2f37d9d7e9 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs @@ -308,6 +308,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders get { return ".ter"; } } + public virtual void SaveFile(ITerrainChannel m_channel, string filename, + int offsetX, int offsetY, + int fileWidth, int fileHeight, + int regionSizeX, int regionSizeY) + { + throw new System.Exception("Not Implemented"); + } + #endregion public override string ToString() diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs index 7403281621..7237f90a38 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs @@ -38,5 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain ITerrainChannel LoadStream(Stream stream); void SaveFile(string filename, ITerrainChannel map); void SaveStream(Stream stream, ITerrainChannel map); + void SaveFile(ITerrainChannel map, string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int regionSizeX, int regionSizeY); } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 8a79d78b22..9c7b2fab9c 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -540,6 +540,39 @@ namespace OpenSim.Region.CoreModules.World.Terrain } } + /// + /// Saves the terrain to a larger terrain file. + /// + /// The terrain file to save + /// The width of the file in units + /// The height of the file in units + /// Where to begin our slice + /// Where to begin our slice + public void SaveToFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) + { + int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX; + int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY; + + if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) + { + // this region is included in the tile request + foreach (KeyValuePair loader in m_loaders) + { + if (filename.EndsWith(loader.Key)) + { + lock (m_scene) + { + loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, + fileWidth, fileHeight, + (int)Constants.RegionSize, + (int)Constants.RegionSize); + } + return; + } + } + } + } + /// /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections /// @@ -860,6 +893,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain SaveToFile((string) args[0]); } + private void InterfaceSaveTileFile(Object[] args) + { + SaveToFile((string)args[0], + (int)args[1], + (int)args[2], + (int)args[3], + (int)args[4]); + } + private void InterfaceBakeTerrain(Object[] args) { UpdateRevertMap(); @@ -1115,6 +1157,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", "Integer"); + Command saveToTileCommand = + new Command("save-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceSaveTileFile, "Saves the current heightmap to the larger file."); + saveToTileCommand.AddArgument("filename", + "The file you wish to save to, the file extension determines the loader to be used. Supported extensions include: " + + supportedFileExtensions, "String"); + saveToTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer"); + saveToTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer"); + saveToTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file", + "Integer"); + saveToTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", + "Integer"); // Terrain adjustments Command fillRegionCommand = new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFillTerrain, "Fills the current heightmap with a specified value."); @@ -1166,6 +1219,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_commander.RegisterCommand("load", loadFromFileCommand); m_commander.RegisterCommand("load-tile", loadFromTileCommand); m_commander.RegisterCommand("save", saveToFileCommand); + m_commander.RegisterCommand("save-tile", saveToTileCommand); m_commander.RegisterCommand("fill", fillRegionCommand); m_commander.RegisterCommand("elevate", elevateCommand); m_commander.RegisterCommand("lower", lowerCommand); From 7592a033df4f81ba985e1d6f57ad0ef488dc5745 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 12 Apr 2011 20:24:28 -0700 Subject: [PATCH 14/45] Moved 3 request handlers from OpenSim.Framework.Servers.HttpServer up to OpenSim.Framework -- just pasted them in WebUtil. This is so that code that uses the Service connectors don't need to include the HttpServer dll -- that was odd. --- .../AsynchronousRestObjectRequester.cs | 192 ---------- .../SynchronousRestFormsRequester.cs | 131 ------- .../SynchronousRestObjectRequester.cs | 122 ------- OpenSim/Framework/WebUtil.cs | 335 ++++++++++++++++++ .../Avatar/Friends/FriendsModule.cs | 2 +- .../InstantMessage/OfflineMessageModule.cs | 1 - .../Asset/AssetServiceInConnectorModule.cs | 1 - .../AuthenticationServiceInConnectorModule.cs | 1 - .../Grid/GridInfoServiceInConnectorModule.cs | 1 - .../HypergridServiceInConnectorModule.cs | 1 - .../InventoryServiceInConnectorModule.cs | 3 +- .../Land/LandServiceInConnectorModule.cs | 1 - .../Login/LLLoginServiceInConnectorModule.cs | 1 - .../NeighbourServiceInConnectorModule.cs | 1 - .../SimulationServiceInConnectorModule.cs | 1 - .../Connectors/Asset/AssetServiceConnector.cs | 1 - .../AuthenticationServiceConnector.cs | 1 - .../AuthorizationServiceConnector.cs | 1 - .../Avatar/AvatarServiceConnector.cs | 1 - .../Freeswitch/RemoteFreeswitchConnector.cs | 1 - .../Friends/FriendsServiceConnector.cs | 1 - .../Connectors/Friends/FriendsSimConnector.cs | 2 +- .../Connectors/Grid/GridServiceConnector.cs | 1 - .../GridUser/GridUserServiceConnector.cs | 1 - .../Inventory/XInventoryConnector.cs | 1 - .../Connectors/Land/LandServiceConnector.cs | 1 - .../Neighbour/NeighbourServiceConnector.cs | 1 - .../Presence/PresenceServiceConnector.cs | 1 - .../UserAccountServiceConnector.cs | 1 - prebuild.xml | 1 - 30 files changed, 338 insertions(+), 472 deletions(-) delete mode 100644 OpenSim/Framework/Servers/HttpServer/AsynchronousRestObjectRequester.cs delete mode 100644 OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs delete mode 100644 OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs diff --git a/OpenSim/Framework/Servers/HttpServer/AsynchronousRestObjectRequester.cs b/OpenSim/Framework/Servers/HttpServer/AsynchronousRestObjectRequester.cs deleted file mode 100644 index 03c12dd560..0000000000 --- a/OpenSim/Framework/Servers/HttpServer/AsynchronousRestObjectRequester.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Net; -using System.Reflection; -using System.Text; -using System.Xml; -using System.Xml.Serialization; -using log4net; - -namespace OpenSim.Framework.Servers.HttpServer -{ - public class AsynchronousRestObjectRequester - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Perform an asynchronous REST request. - /// - /// GET or POST - /// - /// - /// - /// - /// - /// Thrown if we encounter a - /// network issue while posting the request. You'll want to make - /// sure you deal with this as they're not uncommon - // - public static void MakeRequest(string verb, - string requestUrl, TRequest obj, Action action) - { -// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl); - - Type type = typeof (TRequest); - - WebRequest request = WebRequest.Create(requestUrl); - WebResponse response = null; - TResponse deserial = default(TResponse); - XmlSerializer deserializer = new XmlSerializer(typeof (TResponse)); - - request.Method = verb; - - if (verb == "POST") - { - request.ContentType = "text/xml"; - - MemoryStream buffer = new MemoryStream(); - - XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = Encoding.UTF8; - - using (XmlWriter writer = XmlWriter.Create(buffer, settings)) - { - XmlSerializer serializer = new XmlSerializer(type); - serializer.Serialize(writer, obj); - writer.Flush(); - } - - int length = (int) buffer.Length; - request.ContentLength = length; - - request.BeginGetRequestStream(delegate(IAsyncResult res) - { - Stream requestStream = request.EndGetRequestStream(res); - - requestStream.Write(buffer.ToArray(), 0, length); - requestStream.Close(); - - request.BeginGetResponse(delegate(IAsyncResult ar) - { - response = request.EndGetResponse(ar); - Stream respStream = null; - try - { - respStream = response.GetResponseStream(); - deserial = (TResponse)deserializer.Deserialize( - respStream); - } - catch (System.InvalidOperationException) - { - } - finally - { - // Let's not close this - //buffer.Close(); - respStream.Close(); - response.Close(); - } - - action(deserial); - - }, null); - }, null); - - - return; - } - - request.BeginGetResponse(delegate(IAsyncResult res2) - { - try - { - // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't - // documented in MSDN - response = request.EndGetResponse(res2); - - Stream respStream = null; - try - { - respStream = response.GetResponseStream(); - deserial = (TResponse)deserializer.Deserialize(respStream); - } - catch (System.InvalidOperationException) - { - } - finally - { - respStream.Close(); - response.Close(); - } - } - catch (WebException e) - { - if (e.Status == WebExceptionStatus.ProtocolError) - { - if (e.Response is HttpWebResponse) - { - HttpWebResponse httpResponse = (HttpWebResponse)e.Response; - - if (httpResponse.StatusCode != HttpStatusCode.NotFound) - { - // We don't appear to be handling any other status codes, so log these feailures to that - // people don't spend unnecessary hours hunting phantom bugs. - m_log.DebugFormat( - "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}", - verb, requestUrl, httpResponse.StatusCode); - } - } - } - else - { - m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}", verb, requestUrl, e.Status, e.Message); - } - } - catch (Exception e) - { - m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with exception {2}", verb, requestUrl, e); - } - - // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString()); - - try - { - action(deserial); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}", verb, requestUrl, e); - } - - }, null); - } - } -} diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs deleted file mode 100644 index 41ece86047..0000000000 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Net; -using System.Reflection; -using System.Text; -using System.Xml; -using System.Xml.Serialization; - -using log4net; - -namespace OpenSim.Framework.Servers.HttpServer -{ - public class SynchronousRestFormsRequester - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Perform a synchronous REST request. - /// - /// - /// - /// - /// - /// - /// Thrown if we encounter a network issue while posting - /// the request. You'll want to make sure you deal with this as they're not uncommon - public static string MakeRequest(string verb, string requestUrl, string obj) - { - WebRequest request = WebRequest.Create(requestUrl); - request.Method = verb; - string respstring = String.Empty; - - using (MemoryStream buffer = new MemoryStream()) - { - if ((verb == "POST") || (verb == "PUT")) - { - request.ContentType = "text/www-form-urlencoded"; - - int length = 0; - using (StreamWriter writer = new StreamWriter(buffer)) - { - writer.Write(obj); - writer.Flush(); - } - - length = (int)obj.Length; - request.ContentLength = length; - - Stream requestStream = null; - try - { - requestStream = request.GetRequestStream(); - requestStream.Write(buffer.ToArray(), 0, length); - } - catch (Exception e) - { - m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); - } - finally - { - if (requestStream != null) - requestStream.Close(); - } - } - - try - { - using (WebResponse resp = request.GetResponse()) - { - if (resp.ContentLength != 0) - { - Stream respStream = null; - try - { - respStream = resp.GetResponseStream(); - using (StreamReader reader = new StreamReader(respStream)) - { - respstring = reader.ReadToEnd(); - } - } - catch (Exception e) - { - m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); - } - finally - { - if (respStream != null) - respStream.Close(); - } - } - } - } - catch (System.InvalidOperationException) - { - // This is what happens when there is invalid XML - m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving request"); - } - } - return respstring; - } - } -} diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs deleted file mode 100644 index eab463cbd8..0000000000 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Net; -using System.Text; -using System.Xml; -using System.Xml.Serialization; - -namespace OpenSim.Framework.Servers.HttpServer -{ - public class SynchronousRestObjectPoster - { - [Obsolete] - public static TResponse BeginPostObject(string verb, string requestUrl, TRequest obj) - { - return SynchronousRestObjectRequester.MakeRequest(verb, requestUrl, obj); - } - } - - public class SynchronousRestObjectRequester - { - /// - /// Perform a synchronous REST request. - /// - /// - /// - /// - /// - /// - /// Thrown if we encounter a network issue while posting - /// the request. You'll want to make sure you deal with this as they're not uncommon - public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj) - { - Type type = typeof (TRequest); - TResponse deserial = default(TResponse); - - WebRequest request = WebRequest.Create(requestUrl); - request.Method = verb; - - if ((verb == "POST") || (verb == "PUT")) - { - request.ContentType = "text/xml"; - - MemoryStream buffer = new MemoryStream(); - - XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = Encoding.UTF8; - - using (XmlWriter writer = XmlWriter.Create(buffer, settings)) - { - XmlSerializer serializer = new XmlSerializer(type); - serializer.Serialize(writer, obj); - writer.Flush(); - } - - int length = (int) buffer.Length; - request.ContentLength = length; - - Stream requestStream = null; - try - { - requestStream = request.GetRequestStream(); - requestStream.Write(buffer.ToArray(), 0, length); - } - catch (Exception) - { - return deserial; - } - finally - { - if (requestStream != null) - requestStream.Close(); - } - } - - try - { - using (WebResponse resp = request.GetResponse()) - { - if (resp.ContentLength > 0) - { - Stream respStream = resp.GetResponseStream(); - XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); - deserial = (TResponse)deserializer.Deserialize(respStream); - respStream.Close(); - } - } - } - catch (System.InvalidOperationException) - { - // This is what happens when there is invalid XML - } - return deserial; - } - } -} diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 1feeeb31e5..64cd014f5c 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -36,6 +36,9 @@ using System.Net.Security; using System.Reflection; using System.Text; using System.Web; +using System.Xml; +using System.Xml.Serialization; + using log4net; using OpenSim.Framework.Servers.HttpServer; using OpenMetaverse.StructuredData; @@ -625,4 +628,336 @@ namespace OpenSim.Framework } + + public static class AsynchronousRestObjectRequester + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Perform an asynchronous REST request. + /// + /// GET or POST + /// + /// + /// + /// + /// + /// Thrown if we encounter a + /// network issue while posting the request. You'll want to make + /// sure you deal with this as they're not uncommon + // + public static void MakeRequest(string verb, + string requestUrl, TRequest obj, Action action) + { + // m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl); + + Type type = typeof(TRequest); + + WebRequest request = WebRequest.Create(requestUrl); + WebResponse response = null; + TResponse deserial = default(TResponse); + XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); + + request.Method = verb; + + if (verb == "POST") + { + request.ContentType = "text/xml"; + + MemoryStream buffer = new MemoryStream(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + + using (XmlWriter writer = XmlWriter.Create(buffer, settings)) + { + XmlSerializer serializer = new XmlSerializer(type); + serializer.Serialize(writer, obj); + writer.Flush(); + } + + int length = (int)buffer.Length; + request.ContentLength = length; + + request.BeginGetRequestStream(delegate(IAsyncResult res) + { + Stream requestStream = request.EndGetRequestStream(res); + + requestStream.Write(buffer.ToArray(), 0, length); + requestStream.Close(); + + request.BeginGetResponse(delegate(IAsyncResult ar) + { + response = request.EndGetResponse(ar); + Stream respStream = null; + try + { + respStream = response.GetResponseStream(); + deserial = (TResponse)deserializer.Deserialize( + respStream); + } + catch (System.InvalidOperationException) + { + } + finally + { + // Let's not close this + //buffer.Close(); + respStream.Close(); + response.Close(); + } + + action(deserial); + + }, null); + }, null); + + + return; + } + + request.BeginGetResponse(delegate(IAsyncResult res2) + { + try + { + // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't + // documented in MSDN + response = request.EndGetResponse(res2); + + Stream respStream = null; + try + { + respStream = response.GetResponseStream(); + deserial = (TResponse)deserializer.Deserialize(respStream); + } + catch (System.InvalidOperationException) + { + } + finally + { + respStream.Close(); + response.Close(); + } + } + catch (WebException e) + { + if (e.Status == WebExceptionStatus.ProtocolError) + { + if (e.Response is HttpWebResponse) + { + HttpWebResponse httpResponse = (HttpWebResponse)e.Response; + + if (httpResponse.StatusCode != HttpStatusCode.NotFound) + { + // We don't appear to be handling any other status codes, so log these feailures to that + // people don't spend unnecessary hours hunting phantom bugs. + m_log.DebugFormat( + "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}", + verb, requestUrl, httpResponse.StatusCode); + } + } + } + else + { + m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}", verb, requestUrl, e.Status, e.Message); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[ASYNC REQUEST]: Request {0} {1} failed with exception {2}", verb, requestUrl, e); + } + + // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString()); + + try + { + action(deserial); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}", verb, requestUrl, e); + } + + }, null); + } + } + + public static class SynchronousRestFormsRequester + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Perform a synchronous REST request. + /// + /// + /// + /// + /// + /// + /// Thrown if we encounter a network issue while posting + /// the request. You'll want to make sure you deal with this as they're not uncommon + public static string MakeRequest(string verb, string requestUrl, string obj) + { + WebRequest request = WebRequest.Create(requestUrl); + request.Method = verb; + string respstring = String.Empty; + + using (MemoryStream buffer = new MemoryStream()) + { + if ((verb == "POST") || (verb == "PUT")) + { + request.ContentType = "text/www-form-urlencoded"; + + int length = 0; + using (StreamWriter writer = new StreamWriter(buffer)) + { + writer.Write(obj); + writer.Flush(); + } + + length = (int)obj.Length; + request.ContentLength = length; + + Stream requestStream = null; + try + { + requestStream = request.GetRequestStream(); + requestStream.Write(buffer.ToArray(), 0, length); + } + catch (Exception e) + { + m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); + } + finally + { + if (requestStream != null) + requestStream.Close(); + } + } + + try + { + using (WebResponse resp = request.GetResponse()) + { + if (resp.ContentLength != 0) + { + Stream respStream = null; + try + { + respStream = resp.GetResponseStream(); + using (StreamReader reader = new StreamReader(respStream)) + { + respstring = reader.ReadToEnd(); + } + } + catch (Exception e) + { + m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); + } + finally + { + if (respStream != null) + respStream.Close(); + } + } + } + } + catch (System.InvalidOperationException) + { + // This is what happens when there is invalid XML + m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving request"); + } + } + return respstring; + } + } + + public class SynchronousRestObjectPoster + { + [Obsolete] + public static TResponse BeginPostObject(string verb, string requestUrl, TRequest obj) + { + return SynchronousRestObjectRequester.MakeRequest(verb, requestUrl, obj); + } + } + + public class SynchronousRestObjectRequester + { + /// + /// Perform a synchronous REST request. + /// + /// + /// + /// + /// + /// + /// Thrown if we encounter a network issue while posting + /// the request. You'll want to make sure you deal with this as they're not uncommon + public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj) + { + Type type = typeof(TRequest); + TResponse deserial = default(TResponse); + + WebRequest request = WebRequest.Create(requestUrl); + request.Method = verb; + + if ((verb == "POST") || (verb == "PUT")) + { + request.ContentType = "text/xml"; + + MemoryStream buffer = new MemoryStream(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + + using (XmlWriter writer = XmlWriter.Create(buffer, settings)) + { + XmlSerializer serializer = new XmlSerializer(type); + serializer.Serialize(writer, obj); + writer.Flush(); + } + + int length = (int)buffer.Length; + request.ContentLength = length; + + Stream requestStream = null; + try + { + requestStream = request.GetRequestStream(); + requestStream.Write(buffer.ToArray(), 0, length); + } + catch (Exception) + { + return deserial; + } + finally + { + if (requestStream != null) + requestStream.Close(); + } + } + + try + { + using (WebResponse resp = request.GetResponse()) + { + if (resp.ContentLength > 0) + { + Stream respStream = resp.GetResponseStream(); + XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); + deserial = (TResponse)deserializer.Deserialize(respStream); + respStream.Close(); + } + } + } + catch (System.InvalidOperationException) + { + // This is what happens when there is invalid XML + } + return deserial; + } + } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 4d74b2a0a0..5baf0785f4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -34,13 +34,13 @@ using Nini.Config; using Nwc.XmlRpc; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using OpenSim.Services.Connectors.Friends; using OpenSim.Server.Base; -using OpenSim.Framework.Servers.HttpServer; using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using GridRegion = OpenSim.Services.Interfaces.GridRegion; diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index fdfcd104c0..919ea338f4 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -33,7 +33,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Client; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs index e25700d1f7..422f394d7a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs index 02acddc37e..2b5beba374 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs index 6d975afb14..f29c074206 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs index 2f96bcb1ab..d2343c994e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs index 209cf0d3c2..53a8ace14c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs @@ -31,9 +31,8 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; using OpenSim.Server.Base; using OpenSim.Server.Handlers.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs index fcc69e949f..fc642032b5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs index 2a9366c44e..f759470b28 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs index 35518d59f8..5c3263260e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs index 5ee1c97e5f..86b4926ac5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Server.Base; diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index 65b3537041..f1da4fa777 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -34,7 +34,6 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenMetaverse; diff --git a/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs index 6f77a2d8b3..c04e7a4971 100644 --- a/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; diff --git a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs index 4eb4bd2470..35b7109496 100644 --- a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenMetaverse; diff --git a/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs b/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs index 1cd6bf8e1a..1a93ae71c6 100644 --- a/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using IAvatarService = OpenSim.Services.Interfaces.IAvatarService; diff --git a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs index c9bba0b730..d68829996d 100644 --- a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs +++ b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 36b5083860..861c4759a3 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenSim.Server.Base; diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs index 0a7b277e4c..4ffa68c381 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs @@ -32,7 +32,7 @@ using System.Reflection; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; -using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Framework; using OpenMetaverse; using log4net; diff --git a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs index 5092d741e6..e57f28b44e 100644 --- a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs +++ b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs index b3ea865996..738cc06949 100644 --- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs index b3bfcc27df..cd9f2bfcff 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs @@ -34,7 +34,6 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 252f7a1d16..30a73a471c 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -34,7 +34,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenMetaverse; using Nwc.XmlRpc; diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs index 9e444c49bc..2cae02d42a 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs @@ -36,7 +36,6 @@ using System.Text; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using OpenMetaverse; using OpenMetaverse.StructuredData; diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs index 41ebeaf05e..7238afc613 100644 --- a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs index 2a5df83193..f6835b9f2f 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs @@ -33,7 +33,6 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenMetaverse; diff --git a/prebuild.xml b/prebuild.xml index 870ebf300c..81716641c6 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -931,7 +931,6 @@ - From 90b810c27ef4fe3da1796842940af13db61fb91d Mon Sep 17 00:00:00 2001 From: dahlia Date: Tue, 12 Apr 2011 22:47:30 -0700 Subject: [PATCH 15/45] force mesh proxy for simple box prims with path cut --- OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs | 3 +++ OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs index 85e34c1e3d..6df213d851 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs @@ -648,6 +648,9 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin if (pbs.ProfileHollow != 0) iPropertiesNotSupportedDefault++; + if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) + iPropertiesNotSupportedDefault++; + if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) iPropertiesNotSupportedDefault++; diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index eb97f41e3c..a0101af2bb 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -2528,6 +2528,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (pbs.ProfileHollow != 0) iPropertiesNotSupportedDefault++; + if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) + iPropertiesNotSupportedDefault++; + if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) iPropertiesNotSupportedDefault++; From 6613daa82a3bf0d45b0be1b2941646042f9008f4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 17:46:36 +0100 Subject: [PATCH 16/45] Add a regression test for rezzing a single object into a scene from user inventory --- .../ClientStack/LindenUDP/LLClientView.cs | 9 +- .../Tests/InventoryAccessModuleTests.cs | 133 ++++++++++++++++++ .../World/Estate/EstateManagementModule.cs | 4 + prebuild.xml | 1 + 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 8de31d7069..76d7f7964b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4290,6 +4290,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendEstateCovenantInformation(UUID covenant) { +// m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name); + EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); edata.CovenantID = covenant; @@ -4300,8 +4302,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(einfopack, ThrottleOutPacketType.Task); } - public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) + public void SendDetailedEstateData( + UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, + UUID covenant, string abuseEmail, UUID estateOwner) { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant); + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); packet.MethodData.Invoice = invoice; packet.AgentData.TransactionID = UUID.Random(); diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs new file mode 100644 index 0000000000..ecf70ac347 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -0,0 +1,133 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Threading; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Framework.Serialization.External; +using OpenSim.Framework.Communications; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; +using OpenSim.Region.CoreModules.Framework.InventoryAccess; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests +{ + [TestFixture] + public class InventoryAccessModuleTests + { + protected TestScene m_scene; + protected BasicInventoryAccessModule m_iam; + + [SetUp] + public void SetUp() + { + m_iam = new BasicInventoryAccessModule(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); + config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); + + m_scene = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(m_scene, config, m_iam); + } + + [Test] + public void TestRezObject() + { + TestHelper.InMethod(); + log4net.Config.XmlConfigurator.Configure(); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); + + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "My Little Dog Object"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + object1 = new SceneObjectGroup(part1); + } + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + m_scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + string item1Name = "My Little Dog"; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + m_scene.AddInventoryItem(item1); + + AgentCircuitData acd = new AgentCircuitData(); + acd.AgentID = userId; + TestClient tc = new TestClient(acd, m_scene); + + SceneObjectGroup so + = m_iam.RezObject( + tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); + + Assert.That(so, Is.Not.Null); + + SceneObjectPart retrievedPart = m_scene.GetSceneObjectPart(so.UUID); + Assert.That(retrievedPart, Is.Not.Null); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index b6d64acb80..ab90e90b78 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -259,6 +259,10 @@ namespace OpenSim.Region.CoreModules.World.Estate private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) { +// m_log.DebugFormat( +// "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}", +// remoteClient.Name, estateCovenantID); + Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); diff --git a/prebuild.xml b/prebuild.xml index 81716641c6..49063daa57 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2888,6 +2888,7 @@ + From 08fd1d9bbd0878e6ea0ce4abc0a664a70865ea01 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 18:11:04 +0100 Subject: [PATCH 17/45] factor out some test code into the SetUp() --- .../Tests/InventoryAccessModuleTests.cs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index ecf70ac347..5eca753d03 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -54,6 +54,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests { protected TestScene m_scene; protected BasicInventoryAccessModule m_iam; + protected UUID m_userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + protected TestClient m_tc; [SetUp] public void SetUp() @@ -66,20 +68,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests m_scene = SceneSetupHelpers.SetupScene("Inventory"); SceneSetupHelpers.SetupSceneModules(m_scene, config, m_iam); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); + + AgentCircuitData acd = new AgentCircuitData(); + acd.AgentID = m_userId; + m_tc = new TestClient(acd, m_scene); } [Test] public void TestRezObject() { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); +// log4net.Config.XmlConfigurator.Configure(); // Create asset SceneObjectGroup object1; @@ -112,17 +117,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests item1.AssetID = asset1.FullID; item1.ID = item1Id; InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0]; item1.Folder = objsFolder.ID; m_scene.AddInventoryItem(item1); - AgentCircuitData acd = new AgentCircuitData(); - acd.AgentID = userId; - TestClient tc = new TestClient(acd, m_scene); - SceneObjectGroup so = m_iam.RezObject( - tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); + m_tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); Assert.That(so, Is.Not.Null); From dec9c2283b548818409c91a93307334d1c0d9774 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 13 Apr 2011 16:10:18 -0400 Subject: [PATCH 18/45] Add ColladaMesh switch --- .../CoreModules/Avatar/Assets/GetMeshModule.cs | 13 +++++++++++-- .../NewFileAgentInventoryVariablePriceModule.cs | 11 ++++++++++- bin/OpenSimDefaults.ini | 6 +++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs index 878242a447..d2278bc3de 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs @@ -54,6 +54,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets private Scene m_scene; private IAssetService m_assetService; + private bool m_enabled = true; #region IRegionModuleBase Members @@ -65,7 +66,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void Initialise(IConfigSource source) { - + IConfig startupConfig = source.Configs["Startup"]; + if (startupConfig == null) + return; + + if (!startupConfig.GetBoolean("ColladaMesh",true)) + m_enabled = false; } public void AddRegion(Scene pScene) @@ -101,16 +107,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void RegisterCaps(UUID agentID, Caps caps) { + if(!m_enabled) + return; + UUID capID = UUID.Random(); // m_log.Info("[GETMESH]: /CAPS/" + capID); + caps.RegisterHandler("GetMesh", new RestHTTPHandler("GET", "/CAPS/" + capID, delegate(Hashtable m_dhttpMethod) { return ProcessGetMesh(m_dhttpMethod, agentID, caps); })); - } #endregion diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs index 4a42c938d5..fb07cc9ca0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs @@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets private Scene m_scene; // private IAssetService m_assetService; private bool m_dumpAssetsToFile = false; + private bool m_enabled = true; #region IRegionModuleBase Members @@ -67,7 +68,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void Initialise(IConfigSource source) { - + IConfig startupConfig = source.Configs["Startup"]; + if (startupConfig == null) + return; + + if (!startupConfig.GetBoolean("ColladaMesh",true)) + m_enabled = false; } public void AddRegion(Scene pScene) @@ -103,6 +109,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void RegisterCaps(UUID agentID, Caps caps) { + if(!m_enabled) + return; + UUID capID = UUID.Random(); // m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID); diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index f857b8da63..107e859827 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -154,7 +154,11 @@ ; mesh, and use it for collisions. This is currently experimental code and enabling ; it may cause unexpected physics problems. ;UseMeshiesPhysicsMesh = false - + + ; enable / disable Collada mesh support + ; default is true + ; ColladaMesh = true + ; 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 From 58efd761d13bd4f2617fcb3f94bbe265880589e3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 21:17:43 +0100 Subject: [PATCH 19/45] Add coalesced scene objects class and serializer. This is currently only used by the TestRezCoalescedObject() regression test. This structure matches the existing one for SceneObjects and will allow code to be reused by the uuid gatherer, other tests, etc. Test is not yet fully implemented due to a bug in rezzing coalesced objects where they all get the same name as the item. Only one object should get the same name as the item, which appears to be the one selected last when the the objects were coalesced in the first place. This bug will be addressed shortly. --- .../InventoryAccess/InventoryAccessModule.cs | 19 ++- .../Tests/InventoryAccessModuleTests.cs | 79 +++++++++++ .../Framework/Scenes/CoalescedSceneObjects.cs | 128 ++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 15 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 + .../CoalescedSceneObjectsSerializer.cs | 117 ++++++++++++++++ .../Serialization/SceneObjectSerializer.cs | 23 +++- OpenSim/Tests/Common/Setup/AssetHelpers.cs | 15 ++ 8 files changed, 389 insertions(+), 9 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs create mode 100644 OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 73b0a35b7c..cfcfc79c11 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -274,7 +274,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess float minX, minY, minZ; float maxX, maxY, maxZ; - Vector3[] offsets = m_Scene.GetCombinedBoundingBox(objlist, + Vector3[] offsets = Scene.GetCombinedBoundingBox(objlist, out minX, out maxX, out minY, out maxY, out minZ, out maxZ); @@ -289,7 +289,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess XmlDocument doc = new XmlDocument(); SceneObjectGroup g = objlist[i]; doc.LoadXml(xmlStrings[g.UUID]); - XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup"); + XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup"); e.SetAttribute("offsetx", offsets[i].X.ToString()); e.SetAttribute("offsety", offsets[i].Y.ToString()); e.SetAttribute("offsetz", offsets[i].Z.ToString()); @@ -659,9 +659,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess itemId, n.OuterXml); objlist.Add(g); XmlElement el = (XmlElement)n; - float x = Convert.ToSingle(el.GetAttribute("offsetx")); - float y = Convert.ToSingle(el.GetAttribute("offsety")); - float z = Convert.ToSingle(el.GetAttribute("offsetz")); + + string rawX = el.GetAttribute("offsetx"); + string rawY = el.GetAttribute("offsety"); + string rawZ = el.GetAttribute("offsetz"); +// +// m_log.DebugFormat( +// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>", +// g.Name, rawX, rawY, rawZ); + + float x = Convert.ToSingle(rawX); + float y = Convert.ToSingle(rawY); + float z = Convert.ToSingle(rawZ); veclist.Add(new Vector3(x, y, z)); } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 5eca753d03..f8fa424738 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -80,6 +80,85 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests m_tc = new TestClient(acd, m_scene); } + [Test] + public void TestRezCoalescedObject() + { + TestHelper.InMethod(); + log4net.Config.XmlConfigurator.Configure(); + + // Create asset + SceneObjectGroup object1; + { + string partName = "Object1"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + SceneObjectPart part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + object1 = new SceneObjectGroup(part1); + } + + SceneObjectGroup object2; + { + string partName = "Object2"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + SceneObjectPart part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + object2 = new SceneObjectGroup(part1); + } + + CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2); + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, coa); + m_scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + string item1Name = "My Little Dog"; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + m_scene.AddInventoryItem(item1); + + SceneObjectGroup so + = m_iam.RezObject( + m_tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); + + Assert.That(so, Is.Not.Null); + + Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(2)); + + SceneObjectPart retrievedObj1Part = m_scene.GetSceneObjectPart(object1.Name); + Assert.That(retrievedObj1Part, Is.Null); + + retrievedObj1Part = m_scene.GetSceneObjectPart(item1.Name); + Assert.That(retrievedObj1Part, Is.Not.Null); + Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name)); + + // FIXME: Can't test yet due to a bug where objects in coalescence all get the item name when rerezzed. +// SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name); +// Assert.That(retrievedObj2Part, Is.Not.Null); + } + [Test] public void TestRezObject() { diff --git a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs new file mode 100644 index 0000000000..51eac5f3f6 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenMetaverse; + +namespace OpenSim.Region.Framework.Scenes +{ + /// + /// Represents a coalescene of scene objects. A coalescence occurs when objects that are not in the same linkset + /// are grouped together. + /// + public class CoalescedSceneObjects + { + /// + /// The creator of this coalesence, though not necessarily the objects within it. + /// + public UUID CreatorId { get; set; } + + /// + /// The number of objects in this coalesence + /// + public int Count + { + get + { + lock (m_memberObjects) + return m_memberObjects.Count; + } + } + + /// + /// Does this coalesence have any member objects? + /// + public bool HasObjects { get { return Count > 0; } } + + /// + /// Get the objects currently in this coalescence + /// + public List Objects + { + get + { + lock (m_memberObjects) + return new List(m_memberObjects); + } + } + + /// + /// Get the scene that contains the objects in this coalescence. If there are no objects then null is returned. + /// + public Scene Scene + { + get + { + if (!HasObjects) + return null; + else + return Objects[0].Scene; + } + } + + /// + /// At this point, we need to preserve the order of objects added to the coalescence, since the first + /// one will end up matching the item name when rerezzed. + /// + protected List m_memberObjects = new List(); + + public CoalescedSceneObjects(UUID creatorId) + { + CreatorId = creatorId; + } + + public CoalescedSceneObjects(UUID creatorId, params SceneObjectGroup[] objs) : this(creatorId) + { + foreach (SceneObjectGroup obj in objs) + Add(obj); + } + + /// + /// Add an object to the coalescence. + /// + /// + /// The offset of the object within the group + public void Add(SceneObjectGroup obj) + { + lock (m_memberObjects) + m_memberObjects.Add(obj); + } + + /// + /// Removes a scene object from the coalescene + /// + /// + /// true if the object was there to be removed, false if not. + public bool Remove(SceneObjectGroup obj) + { + lock (m_memberObjects) + return m_memberObjects.Remove(obj); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f0acc38820..e6dd48940f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4839,7 +4839,20 @@ namespace OpenSim.Region.Framework.Scenes } } - public Vector3[] GetCombinedBoundingBox(List objects, out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) + /// + /// Get the volume of space that will encompass all the given objects. + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3[] GetCombinedBoundingBox( + List objects, + out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) { minX = 256; maxX = -256; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 97af0a0b47..72f040252f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -997,6 +997,8 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) { +// m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name); + if (p.Name == name) { sop = p; diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs new file mode 100644 index 0000000000..3af2f76340 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -0,0 +1,117 @@ +/* + * 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.Drawing; +using System.IO; +using System.Reflection; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.Framework.Scenes.Serialization +{ + /// + /// Serialize and deserialize coalesced scene objects. + /// + public class CoalescedSceneObjectsSerializer + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Serialize coalesced objects to Xml + /// + /// + /// + public static string ToXml(CoalescedSceneObjects coa) + { + // TODO: Should probably return an empty xml serialization rather than a blank string + if (!coa.HasObjects) + return ""; + + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter writer = new XmlTextWriter(sw)) + { + List coaObjects = coa.Objects; + +// m_log.DebugFormat( +// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing {0} objects for coalesced object", +// coaObjects.Count); + + float minX, minY, minZ; + float maxX, maxY, maxZ; + + Vector3[] offsets = Scene.GetCombinedBoundingBox(coaObjects, + out minX, out maxX, out minY, out maxY, + out minZ, out maxZ); + + writer.WriteStartElement("CoalescedObject"); + + float sizeX = maxX - minX; + float sizeY = maxY - minY; + float sizeZ = maxZ - minZ; + + writer.WriteAttributeString("x", sizeX.ToString()); + writer.WriteAttributeString("y", sizeY.ToString()); + writer.WriteAttributeString("z", sizeZ.ToString()); + + // Embed the offsets into the group XML + for (int i = 0; i < coaObjects.Count; i++) + { + SceneObjectGroup obj = coaObjects[i]; + +// m_log.DebugFormat( +// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing offset for object {0}, {1}", +// i, obj.Name); + + writer.WriteStartElement("SceneObjectGroup"); + writer.WriteAttributeString("offsetx", offsets[i].X.ToString()); + writer.WriteAttributeString("offsety", offsets[i].Y.ToString()); + writer.WriteAttributeString("offsetz", offsets[i].Z.ToString()); + + SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, true); + + writer.WriteEndElement(); + } + + writer.WriteEndElement(); // CoalescedObject + } + + string output = sw.ToString(); + +// m_log.Debug(output); + + return output; + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index b412e25579..bb8a83a1af 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -139,6 +139,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization return sw.ToString(); } } + /// /// Serialize a scene object to the original xml format @@ -146,11 +147,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// /// public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer) + { + ToOriginalXmlFormat(sceneObject, writer, false); + } + + /// + /// Serialize a scene object to the original xml format + /// + /// + /// + /// If false, don't write the enclosing SceneObjectGroup element + /// + public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer, bool noRootElement) { //m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", Name); //int time = System.Environment.TickCount; - writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); + if (!noRootElement) + writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); + writer.WriteStartElement(String.Empty, "RootPart", String.Empty); ToXmlFormat(sceneObject.RootPart, writer); writer.WriteEndElement(); @@ -170,10 +185,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteEndElement(); // OtherParts sceneObject.SaveScriptedState(writer); - writer.WriteEndElement(); // SceneObjectGroup + + if (!noRootElement) + writer.WriteEndElement(); // SceneObjectGroup //m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); - } + } protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer) { diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Setup/AssetHelpers.cs index ff4423f7ab..af66d7f0a7 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Setup/AssetHelpers.cs @@ -71,6 +71,21 @@ namespace OpenSim.Tests.Common Encoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)), sog.OwnerID); } + + /// + /// Create an asset from the given scene object. + /// + /// + /// + /// + public static AssetBase CreateAsset(UUID assetUuid, CoalescedSceneObjects coa) + { + return CreateAsset( + assetUuid, + AssetType.Object, + Encoding.ASCII.GetBytes(CoalescedSceneObjectsSerializer.ToXml(coa)), + coa.CreatorId); + } /// /// Create an asset from the given data. From d8d28c37372718aa593ead5c85cd45ced83766a5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 21:31:45 +0100 Subject: [PATCH 20/45] Fix bug where rezzing coalesced objects would give all objects the same name as the item. This now only happens for the first object (which was the item selected last when the coalesce was originally taken) This matches the expected behaviour of the environment as seen on the Linden Labs grid. --- .../InventoryAccess/InventoryAccessModule.cs | 13 +++++++++---- .../Tests/InventoryAccessModuleTests.cs | 5 ++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index cfcfc79c11..1f8bad1eb5 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -762,10 +762,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. - rootPart.Name = item.Name; - rootPart.Description = item.Description; - rootPart.ObjectSaleType = item.SaleType; - rootPart.SalePrice = item.SalePrice; + // + // Only do these for the first object if we are rezzing a coalescence. + if (i == 0) + { + rootPart.Name = item.Name; + rootPart.Description = item.Description; + rootPart.ObjectSaleType = item.SaleType; + rootPart.SalePrice = item.SalePrice; + } group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if ((rootPart.OwnerID != item.Owner) || diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index f8fa424738..0f2b6108ad 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -154,9 +154,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests Assert.That(retrievedObj1Part, Is.Not.Null); Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name)); - // FIXME: Can't test yet due to a bug where objects in coalescence all get the item name when rerezzed. -// SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name); -// Assert.That(retrievedObj2Part, Is.Not.Null); + SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name); + Assert.That(retrievedObj2Part, Is.Not.Null); } [Test] From 68cc5b46fefdf4db68cae1202086257ce731f8a1 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 21:48:16 +0100 Subject: [PATCH 21/45] refactor: move code to obtain the coalescence size and object offsets into CoalescedSceneObjects from the serializer. --- .../Tests/InventoryAccessModuleTests.cs | 2 +- .../Framework/Scenes/CoalescedSceneObjects.cs | 26 ++++++++++++++++++ .../CoalescedSceneObjectsSerializer.cs | 27 +++++++++---------- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 0f2b6108ad..c197cb9b1b 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests public void TestRezCoalescedObject() { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); +// log4net.Config.XmlConfigurator.Configure(); // Create asset SceneObjectGroup object1; diff --git a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs index 51eac5f3f6..af8ccda6c2 100644 --- a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs +++ b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs @@ -124,5 +124,31 @@ namespace OpenSim.Region.Framework.Scenes lock (m_memberObjects) return m_memberObjects.Remove(obj); } + + /// + /// Get the total size of the coalescence (the size required to cover all the objects within it) and the + /// offsets of each of those objects. + /// + /// + /// + /// An array of offsets. The order of objects is the same as returned from the Objects property + /// + public Vector3[] GetSizeAndOffsets(out Vector3 size) + { + float minX, minY, minZ; + float maxX, maxY, maxZ; + + Vector3[] offsets + = Scene.GetCombinedBoundingBox( + Objects, out minX, out maxX, out minY, out maxY, out minZ, out maxZ); + + float sizeX = maxX - minX; + float sizeY = maxY - minY; + float sizeZ = maxZ - minZ; + + size = new Vector3(sizeX, sizeY, sizeZ); + + return offsets; + } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index 3af2f76340..a0e120a9ac 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -42,6 +42,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// /// Serialize and deserialize coalesced scene objects. /// + /// + /// Deserialization not yet here. + /// public class CoalescedSceneObjectsSerializer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -60,29 +63,23 @@ namespace OpenSim.Region.Framework.Scenes.Serialization using (StringWriter sw = new StringWriter()) { using (XmlTextWriter writer = new XmlTextWriter(sw)) - { + { + Vector3 size; + List coaObjects = coa.Objects; // m_log.DebugFormat( // "[COALESCED SCENE OBJECTS SERIALIZER]: Writing {0} objects for coalesced object", // coaObjects.Count); - float minX, minY, minZ; - float maxX, maxY, maxZ; - - Vector3[] offsets = Scene.GetCombinedBoundingBox(coaObjects, - out minX, out maxX, out minY, out maxY, - out minZ, out maxZ); + // This is weak - we're relying on the set of coalesced objects still being identical + Vector3[] offsets = coa.GetSizeAndOffsets(out size); writer.WriteStartElement("CoalescedObject"); - float sizeX = maxX - minX; - float sizeY = maxY - minY; - float sizeZ = maxZ - minZ; - - writer.WriteAttributeString("x", sizeX.ToString()); - writer.WriteAttributeString("y", sizeY.ToString()); - writer.WriteAttributeString("z", sizeZ.ToString()); + writer.WriteAttributeString("x", size.X.ToString()); + writer.WriteAttributeString("y", size.Y.ToString()); + writer.WriteAttributeString("z", size.Z.ToString()); // Embed the offsets into the group XML for (int i = 0; i < coaObjects.Count; i++) @@ -100,7 +97,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, true); - writer.WriteEndElement(); + writer.WriteEndElement(); // SceneObjectGroup } writer.WriteEndElement(); // CoalescedObject From c81f5bfc5c3cb0bac2a89ee846099dcaae1f357b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 22:29:12 +0100 Subject: [PATCH 22/45] Adjust the quanterions used in the rez coalsced object tests to get sensible bounding box and offset numbers. Extend test to check position of objects in the rezzed coalescence. --- .../Tests/InventoryAccessModuleTests.cs | 16 ++++++++++++---- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++++ .../Region/Framework/Scenes/SceneObjectPart.cs | 9 ++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index c197cb9b1b..c76a30af69 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -93,12 +93,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Quaternion rotationOffset = Quaternion.Identity; Vector3 offsetPosition = new Vector3(5, 10, 15); SceneObjectPart part1 = new SceneObjectPart( ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Scale = new Vector3(1, 1, 1); part1.Name = partName; object1 = new SceneObjectGroup(part1); @@ -109,13 +110,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests string partName = "Object2"; UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 groupPosition = new Vector3(20, 40, 60); + Quaternion rotationOffset = Quaternion.Identity; Vector3 offsetPosition = new Vector3(5, 10, 15); SceneObjectPart part1 = new SceneObjectPart( ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Scale = new Vector3(1, 1, 1); part1.Name = partName; object2 = new SceneObjectGroup(part1); @@ -141,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests SceneObjectGroup so = m_iam.RezObject( - m_tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); + m_tc, item1Id, new Vector3(100, 100, 100), Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); Assert.That(so, Is.Not.Null); @@ -154,8 +156,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests Assert.That(retrievedObj1Part, Is.Not.Null); Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name)); + // Bottom of coalescence is placed on ground, hence we end up with 100.5 rather than 85 since the bottom + // object is unit square. + Assert.That(retrievedObj1Part.AbsolutePosition, Is.EqualTo(new Vector3(95, 90, 100.5f))); + SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name); Assert.That(retrievedObj2Part, Is.Not.Null); + Assert.That(retrievedObj2Part.Name, Is.EqualTo(object2.Name)); + Assert.That(retrievedObj2Part.AbsolutePosition, Is.EqualTo(new Vector3(105, 110, 130.5f))); } [Test] diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e6dd48940f..fdd5205de8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4870,6 +4870,10 @@ namespace OpenSim.Region.Framework.Scenes Vector3 vec = g.AbsolutePosition; g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); + +// m_log.DebugFormat( +// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", +// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); ominX += vec.X; omaxX += vec.X; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4d5eedfc95..ce1e6b8614 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2088,7 +2088,14 @@ namespace OpenSim.Region.Framework.Scenes axPos *= parentRot; Vector3 translationOffsetPosition = axPos; - return GroupPosition + translationOffsetPosition; + +// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); + + Vector3 worldPos = GroupPosition + translationOffsetPosition; + +// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); + + return worldPos; } /// From c5465414b64d835128827976cc3da32aa462e6a3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Apr 2011 22:55:26 +0100 Subject: [PATCH 23/45] Use common coalesced serialization code for both tests and the InventoryAccessModule. Continue to restore original absolute positions of stored scene objects, though it's possible that these aren't used again --- .../InventoryAccess/InventoryAccessModule.cs | 67 ++++--------------- 1 file changed, 13 insertions(+), 54 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 1f8bad1eb5..c0946f4d52 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -222,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess deletes[g.OwnerID].Add(g); } - // This is pethod scoped and will be returned. It will be the + // This is method scoped and will be returned. It will be the // last created asset id UUID assetID = UUID.Zero; @@ -230,8 +230,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // with distinct destinations as well. foreach (List objlist in deletes.Values) { - Dictionary xmlStrings = - new Dictionary(); + CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); + Dictionary originalPositions = new Dictionary(); foreach (SceneObjectGroup objectGroup in objlist) { @@ -245,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess : objectGroup.AbsolutePosition.X, objectGroup.AbsolutePosition.Z); - Vector3 originalPosition = objectGroup.AbsolutePosition; + originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; @@ -259,59 +259,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess (uint)PermissionMask.Modify); objectGroup.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; - - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); - - objectGroup.AbsolutePosition = originalPosition; - - xmlStrings[objectGroup.UUID] = sceneObjectXml; + + coa.Add(objectGroup); } string itemXml; if (objlist.Count > 1) - { - float minX, minY, minZ; - float maxX, maxY, maxZ; - - Vector3[] offsets = Scene.GetCombinedBoundingBox(objlist, - out minX, out maxX, out minY, out maxY, - out minZ, out maxZ); - - // CreateWrapper - XmlDocument itemDoc = new XmlDocument(); - XmlElement root = itemDoc.CreateElement("", "CoalescedObject", ""); - itemDoc.AppendChild(root); - - // Embed the offsets into the group XML - for ( int i = 0 ; i < objlist.Count ; i++ ) - { - XmlDocument doc = new XmlDocument(); - SceneObjectGroup g = objlist[i]; - doc.LoadXml(xmlStrings[g.UUID]); - XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup"); - e.SetAttribute("offsetx", offsets[i].X.ToString()); - e.SetAttribute("offsety", offsets[i].Y.ToString()); - e.SetAttribute("offsetz", offsets[i].Z.ToString()); - - XmlNode objectNode = itemDoc.ImportNode(e, true); - root.AppendChild(objectNode); - } - - float sizeX = maxX - minX; - float sizeY = maxY - minY; - float sizeZ = maxZ - minZ; - - root.SetAttribute("x", sizeX.ToString()); - root.SetAttribute("y", sizeY.ToString()); - root.SetAttribute("z", sizeZ.ToString()); - - itemXml = itemDoc.InnerXml; - } + itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); else - { - itemXml = xmlStrings[objlist[0].UUID]; - } + itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); + + // Restore the position of each group now that it has been stored to inventory. + foreach (SceneObjectGroup objectGroup in objlist) + objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; // Get the user info of the item destination // @@ -332,7 +293,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { // All returns / deletes go to the object owner // - userID = objlist[0].RootPart.OwnerID; } @@ -346,7 +306,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // Delete is treated like return in this case // Deleting your own items makes them go to trash // - + InventoryFolderBase folder = null; InventoryItemBase item = null; @@ -548,7 +508,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return assetID; } - /// /// Rez an object into the scene from the user's inventory /// From 6ed6b46aad85b66dd3c50fcf17d108a8da42c5ff Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 13 Apr 2011 21:01:51 -0700 Subject: [PATCH 24/45] Comment out the warning if the prioritizer runs without a fully initialized scene presence. Not sure why we are dumping updates to a client that isn't there yet... --- OpenSim/Region/Framework/Scenes/Prioritizer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 4694e2b684..e3ed905c2f 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -166,7 +166,11 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence presence = m_scene.GetScenePresence(client.AgentId); if (presence == null) { - m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId); + // this shouldn't happen, it basically means that we are prioritizing + // updates to send to a client that doesn't have a presence in the scene + // seems like there's race condition here... + + // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId); // throw new InvalidOperationException("Prioritization agent not defined"); return Int32.MaxValue; } From aaf912586948a3d0d9bb918952766ba48e90fd18 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 14 Apr 2011 17:33:55 +0100 Subject: [PATCH 25/45] simplify coalesced object tests by using existing scene object set up utils this change makes it possible to set an absolute position on a group before it is put into a scene. --- .../Tests/InventoryAccessModuleTests.cs | 40 +++---------------- .../Framework/Scenes/SceneObjectGroup.cs | 21 ++++++---- 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index c76a30af69..9fc77a74a6 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -87,41 +87,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests // log4net.Config.XmlConfigurator.Configure(); // Create asset - SceneObjectGroup object1; - { - string partName = "Object1"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = Quaternion.Identity; - Vector3 offsetPosition = new Vector3(5, 10, 15); - - SceneObjectPart part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Scale = new Vector3(1, 1, 1); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - } + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "Object1", 0x20); + object1.AbsolutePosition = new Vector3(15, 30, 45); + object1.Parts[0].Scale = new Vector3(1, 1, 1); - SceneObjectGroup object2; - { - string partName = "Object2"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(20, 40, 60); - Quaternion rotationOffset = Quaternion.Identity; - Vector3 offsetPosition = new Vector3(5, 10, 15); - - SceneObjectPart part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Scale = new Vector3(1, 1, 1); - part1.Name = partName; - - object2 = new SceneObjectGroup(part1); - } + SceneObjectGroup object2 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "Object2", 0x40); + object2.AbsolutePosition = new Vector3(25, 50, 75); + object2.Parts[0].Scale = new Vector3(1, 1, 1); CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ca7d9d9d57..9bb50db921 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -296,11 +296,14 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 val = value; - if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) - || m_scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || m_scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) - && !IsAttachmentCheckFull() && (!m_scene.LoadingPrims)) + if (Scene != null) { - m_scene.CrossPrimGroupIntoNewRegion(val, this, true); + if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) + || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) + && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) + { + m_scene.CrossPrimGroupIntoNewRegion(val, this, true); + } } if (RootPart.GetStatusSandbox()) @@ -308,8 +311,11 @@ namespace OpenSim.Region.Framework.Scenes if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) { RootPart.ScriptSetPhysicsStatus(false); - Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), - ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); + + if (Scene != null) + Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), + ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); + return; } } @@ -326,7 +332,8 @@ namespace OpenSim.Region.Framework.Scenes //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); //} - m_scene.EventManager.TriggerParcelPrimCountTainted(); + if (Scene != null) + Scene.EventManager.TriggerParcelPrimCountTainted(); } } From c644ab6a2c902c829a0dc88d08780a4411b4cd29 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 14 Apr 2011 20:21:44 +0100 Subject: [PATCH 26/45] Make scene object parts created by the test utils unit sized. --- .../InventoryAccess/Tests/InventoryAccessModuleTests.cs | 4 +--- OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 9fc77a74a6..60a932d764 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -89,11 +89,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests // Create asset SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "Object1", 0x20); object1.AbsolutePosition = new Vector3(15, 30, 45); - object1.Parts[0].Scale = new Vector3(1, 1, 1); SceneObjectGroup object2 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "Object2", 0x40); - object2.AbsolutePosition = new Vector3(25, 50, 75); - object2.Parts[0].Scale = new Vector3(1, 1, 1); + object2.AbsolutePosition = new Vector3(25, 50, 75); CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2); diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 709dd78063..eb08b62f19 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -472,10 +472,10 @@ namespace OpenSim.Tests.Common.Setup /// /// public static SceneObjectPart CreateSceneObjectPart(string name, UUID id, UUID ownerId) - { + { return new SceneObjectPart( ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = name, UUID = id }; + { Name = name, UUID = id, Scale = new Vector3(1, 1, 1) }; } /// From e4392648248d11699772aac42db753ae4f84495f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 14 Apr 2011 20:23:48 +0100 Subject: [PATCH 27/45] simplify TestRezObject() --- .../Tests/InventoryAccessModuleTests.cs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 60a932d764..7a7a8c23f7 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -143,23 +143,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests // log4net.Config.XmlConfigurator.Configure(); // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "My Little Dog Object"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - } + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "My Little Dog Object", 0x40); UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); From 1569148b49f188f3c46f9fd8ffa096efc70f72fa Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 14 Apr 2011 20:32:27 +0100 Subject: [PATCH 28/45] simplify TestSaveItemToIarV0_1() --- .../Archiver/Tests/InventoryArchiverTests.cs | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 7f156f8904..9e3e7d4e75 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -84,24 +84,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "My Little Dog Object"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - m_scene.AddNewSceneObject(object1, false); - } + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); From 55387542eaae8ab27c4709ae5b923d9d2d2a4431 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 14 Apr 2011 20:35:00 +0100 Subject: [PATCH 29/45] simplify InventoryArchiveTestCase setup --- .../Tests/InventoryArchiveTestCase.cs | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index e5127a0118..7ee6f28285 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -105,24 +105,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests MemoryStream archiveWriteStream = new MemoryStream(); // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "Ray Gun Object"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(object1, false); - } + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50); UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); From 821e67fb950721c0bb8105318e41d7982cf986f2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 14 Apr 2011 20:59:52 +0100 Subject: [PATCH 30/45] implement stub TestLoadCoalesecedItem(). Doesn't do what it's meant to do yet. --- .../Tests/InventoryArchiveTestCase.cs | 35 ++++++++++++++++--- .../Archiver/Tests/InventoryArchiverTests.cs | 17 +++++++++ OpenSim/Tests/Common/Setup/AssetHelpers.cs | 18 ++++++++-- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 7ee6f28285..f2d050c16a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -68,17 +68,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), FirstName = "Mr", LastName = "Tiddles" }; + protected UserAccount m_uaLL1 = new UserAccount { PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), FirstName = "Lord", LastName = "Lucan" }; + protected UserAccount m_uaLL2 = new UserAccount { PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), FirstName = "Lord", - LastName = "Lucan" }; + LastName = "Lucan" }; + protected string m_item1Name = "Ray Gun Item"; + protected string m_coaItemName = "Coalesced Item"; [SetUp] public virtual void SetUp() @@ -104,7 +108,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests MemoryStream archiveWriteStream = new MemoryStream(); - // Create asset + // Create scene object asset UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50); @@ -112,7 +116,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); scene.AssetService.Store(asset1); - // Create item + // Create scene object item InventoryItemBase item1 = new InventoryItemBase(); item1.Name = m_item1Name; item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); @@ -123,8 +127,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; scene.AddInventoryItem(item1); + // Create coalesced objects asset + SceneObjectGroup cobj1 = SceneSetupHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120); + cobj1.AbsolutePosition = new Vector3(15, 30, 45); + + SceneObjectGroup cobj2 = SceneSetupHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140); + cobj2.AbsolutePosition = new Vector3(25, 50, 75); + + CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2); + + AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa); + scene.AssetService.Store(coaAsset); + + // Create coalesced objects inventory item + InventoryItemBase coaItem = new InventoryItemBase(); + coaItem.Name = m_coaItemName; + coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); + coaItem.AssetID = asset1.FullID; + coaItem.GroupID = UUID.Random(); + coaItem.CreatorIdAsUuid = m_uaLL1.PrincipalID; + coaItem.Owner = m_uaLL1.PrincipalID; + coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; + scene.AddInventoryItem(coaItem); + archiverModule.ArchiveInventory( - Guid.NewGuid(), m_uaLL1.FirstName, m_uaLL1.LastName, m_item1Name, "hampshire", archiveWriteStream); + Guid.NewGuid(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream); m_iarStreamBytes = archiveWriteStream.ToArray(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 9e3e7d4e75..0c4e364765 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -257,5 +257,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); } + + [Test] + public void TestLoadCoalesecedItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); + m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); + + InventoryItemBase coaItem + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); + + Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); + + // TODO: Check that the loaded coalesence is valid and that the required scene object assets are around + } } } \ No newline at end of file diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Setup/AssetHelpers.cs index af66d7f0a7..971c6bcf36 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Setup/AssetHelpers.cs @@ -55,7 +55,7 @@ namespace OpenSim.Tests.Common AssetBase asset = CreateAsset(UUID.Random(), AssetType.Notecard, "hello", creatorId); scene.AssetService.Store(asset); return asset; - } + } /// /// Create an asset from the given scene object. @@ -72,6 +72,20 @@ namespace OpenSim.Tests.Common sog.OwnerID); } + /// + /// Create an asset from the given scene object. + /// + /// + /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" + /// will be used. + /// + /// + /// + public static AssetBase CreateAsset(int assetUuidTail, CoalescedSceneObjects coa) + { + return CreateAsset(new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", assetUuidTail)), coa); + } + /// /// Create an asset from the given scene object. /// @@ -85,7 +99,7 @@ namespace OpenSim.Tests.Common AssetType.Object, Encoding.ASCII.GetBytes(CoalescedSceneObjectsSerializer.ToXml(coa)), coa.CreatorId); - } + } /// /// Create an asset from the given data. From a0d80140f2d0ad6dd63970a3a3d5c0da8320ae75 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 00:42:06 +0100 Subject: [PATCH 31/45] Make all the objects in a coalescence reappears after being loaded from an IAR. This still doesn't work proprerly since some required textures/contained item assets might be missing. From pure code inspection, it looks like the uuid gatherer may get most asset uuids because the scene object serializer naively pulls non-root parts from all contained scene objects into one mega-object. However, root part uuids may well still be missing, and there may be other odd artifacts from this bug. It appears that storing the size of the coalescence and the offsets is redundant, since one can work out this information from the position data already in the scene object groups. --- .../Archiver/InventoryArchiveReadRequest.cs | 28 ++++++++--- .../Tests/InventoryArchiveTestCase.cs | 2 +- .../Archiver/Tests/InventoryArchiverTests.cs | 43 ++++++++++------- .../Asset/LocalAssetServiceConnector.cs | 2 + .../CoalescedSceneObjectsSerializer.cs | 47 ++++++++++++++++--- OpenSim/Services/AssetService/AssetService.cs | 10 +++- OpenSim/Services/Interfaces/IAssetService.cs | 5 ++ OpenSim/Tests/Common/Mock/MockAssetService.cs | 22 +++++++-- OpenSim/Tests/Common/Setup/AssetHelpers.cs | 7 +++ .../Tests/Common/Setup/SceneSetupHelpers.cs | 7 ++- 10 files changed, 134 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 01170aaf65..f3d2f26cfe 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -471,16 +471,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (m_creatorIdForAssetId.ContainsKey(assetId)) { string xmlData = Utils.BytesToString(data); - SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - foreach (SceneObjectPart sop in sog.Parts) + List sceneObjects = new List(); + + CoalescedSceneObjects coa = null; + if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) { - if (sop.CreatorData == null || sop.CreatorData == "") - { - sop.CreatorID = m_creatorIdForAssetId[assetId]; - } +// m_log.DebugFormat( +// "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); + + sceneObjects.AddRange(coa.Objects); + } + else + { + sceneObjects.Add(SceneObjectSerializer.FromOriginalXmlFormat(xmlData)); } - data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)); + foreach (SceneObjectGroup sog in sceneObjects) + foreach (SceneObjectPart sop in sog.Parts) + if (sop.CreatorData == null || sop.CreatorData == "") + sop.CreatorID = m_creatorIdForAssetId[assetId]; + + if (coa != null) + data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa)); + else + data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sceneObjects[0])); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index f2d050c16a..e2316f0bdd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests InventoryItemBase coaItem = new InventoryItemBase(); coaItem.Name = m_coaItemName; coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); - coaItem.AssetID = asset1.FullID; + coaItem.AssetID = coaAsset.FullID; coaItem.GroupID = UUID.Random(); coaItem.CreatorIdAsUuid = m_uaLL1.PrincipalID; coaItem.Owner = m_uaLL1.PrincipalID; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 0c4e364765..f747c899de 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -62,9 +62,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); m_archiverModule = new InventoryArchiverModule(); - m_scene = SceneSetupHelpers.SetupScene("Inventory"); + m_scene = SceneSetupHelpers.SetupScene("asset inventory"); SceneSetupHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); } + + [Test] + public void TestLoadCoalesecedItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); + m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); + + InventoryItemBase coaItem + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); + + Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); + + string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); + + CoalescedSceneObjects coa; + bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); + + Assert.That(readResult, Is.True); + + // TODO: Check that the loaded coalesence is valid and that the required scene object assets are around + } /// /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive @@ -257,22 +281,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); } - - [Test] - public void TestLoadCoalesecedItem() - { - TestHelper.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); - m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); - - InventoryItemBase coaItem - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); - - Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); - - // TODO: Check that the loaded coalesence is valid and that the required scene object assets are around - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 1b3419d12f..51d1d599c5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -195,6 +195,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset public byte[] GetData(string id) { +// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); + AssetBase asset = m_Cache.Get(id); if (asset != null) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index a0e120a9ac..babcb54ae9 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -55,11 +55,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// /// public static string ToXml(CoalescedSceneObjects coa) - { - // TODO: Should probably return an empty xml serialization rather than a blank string - if (!coa.HasObjects) - return ""; - + { using (StringWriter sw = new StringWriter()) { using (XmlTextWriter writer = new XmlTextWriter(sw)) @@ -105,10 +101,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization string output = sw.ToString(); -// m_log.Debug(output); +// Console.WriteLine(output); return output; } } + + public static bool TryFromXml(string xml, out CoalescedSceneObjects coa) + { +// m_log.DebugFormat("[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() deserializing {0}", xml); + + coa = null; + + using (StringReader sr = new StringReader(xml)) + { + using (XmlTextReader reader = new XmlTextReader(sr)) + { + reader.Read(); + if (reader.Name != "CoalescedObject") + { +// m_log.DebugFormat( +// "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false", +// reader.Name); + + return false; + } + + coa = new CoalescedSceneObjects(UUID.Zero); + reader.Read(); + + while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject") + { + if (reader.Name == "SceneObjectGroup") + { + string soXml = reader.ReadOuterXml(); + coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml)); + } + } + + reader.ReadEndElement(); // CoalescedObject + } + } + + return true; + } } } \ No newline at end of file diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index a81af4355a..e1f90b6e18 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -89,6 +89,8 @@ namespace OpenSim.Services.AssetService public virtual AssetBase Get(string id) { +// m_log.DebugFormat("[ASSET SERVICE]: Get asset for {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) @@ -107,6 +109,8 @@ namespace OpenSim.Services.AssetService public virtual AssetMetadata GetMetadata(string id) { +// m_log.DebugFormat("[ASSET SERVICE]: Get asset metadata for {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) @@ -121,6 +125,8 @@ namespace OpenSim.Services.AssetService public virtual byte[] GetData(string id) { +// m_log.DebugFormat("[ASSET SERVICE]: Get asset data for {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) @@ -150,7 +156,9 @@ namespace OpenSim.Services.AssetService public virtual string Store(AssetBase asset) { - //m_log.DebugFormat("[ASSET SERVICE]: Store asset {0} {1}", asset.Name, asset.ID); +// m_log.DebugFormat( +// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); + m_Database.StoreAsset(asset); return asset.ID; diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 3be6815728..1ac1cec358 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -48,6 +48,11 @@ namespace OpenSim.Services.Interfaces /// AssetMetadata GetMetadata(string id); + /// + /// Get an asset's data, ignoring the metadata. + /// + /// + /// null if there is no such asset byte[] GetData(string id); /// diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs index 4118308bed..9d7c5e29e6 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetService.cs @@ -54,13 +54,19 @@ namespace OpenSim.Tests.Common.Mock public AssetBase Get(string id) { - m_log.DebugFormat("[MOCK ASSET SERVICE]: Getting asset with id {0}", id); +// m_log.DebugFormat("[MOCK ASSET SERVICE]: Getting asset with id {0}", id); AssetBase asset; if (Assets.ContainsKey(id)) + { asset = Assets[id]; +// m_log.DebugFormat( +// "[MOCK ASSET SERVICE]: Got asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); + } else - asset = null; + { + asset = null; + } return asset; } @@ -77,7 +83,14 @@ namespace OpenSim.Tests.Common.Mock public byte[] GetData(string id) { - throw new System.NotImplementedException(); +// m_log.DebugFormat("[MOCK ASSET SERVICE]: Requesting data for asset {0}", id); + + AssetBase asset = Get(id); + + if (asset == null) + return null; + else + return asset.Data; } public bool Get(string id, object sender, AssetRetrieved handler) @@ -89,7 +102,8 @@ namespace OpenSim.Tests.Common.Mock public string Store(AssetBase asset) { - m_log.DebugFormat("[MOCK ASSET SERVICE]: Storing asset {0}", asset.ID); +// m_log.DebugFormat( +// "[MOCK ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); Assets[asset.ID] = asset; diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Setup/AssetHelpers.cs index 971c6bcf36..d572249997 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Setup/AssetHelpers.cs @@ -30,6 +30,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Services.Interfaces; namespace OpenSim.Tests.Common { @@ -118,5 +119,11 @@ namespace OpenSim.Tests.Common asset.Data = data; return asset; } + + public static string ReadAssetAsString(IAssetService assetService, UUID uuid) + { + byte[] assetData = assetService.GetData(uuid.ToString()); + return Encoding.ASCII.GetString(assetData); + } } } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index eb08b62f19..837f4e235f 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -168,14 +168,17 @@ namespace OpenSim.Tests.Common.Setup { LocalAssetServicesConnector assetService = new LocalAssetServicesConnector(); IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("AssetService"); + config.AddConfig("Modules"); config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); + + config.AddConfig("AssetService"); if (real) config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); else config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:MockAssetService"); + config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); + assetService.Initialise(config); assetService.AddRegion(testScene); assetService.RegionLoaded(testScene); From ad70cddcfc48182f75be7643297cea2a9d20ac91 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 00:56:40 +0100 Subject: [PATCH 32/45] extend TestLoadCoalesecedItem() to check loaded object ids and positions --- .../Inventory/Archiver/Tests/InventoryArchiverTests.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index f747c899de..69c5dcdab1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -86,8 +86,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); Assert.That(readResult, Is.True); + Assert.That(coa.Count, Is.EqualTo(2)); - // TODO: Check that the loaded coalesence is valid and that the required scene object assets are around + List coaObjects = coa.Objects; + Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); + Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); + + Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); + Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); } /// From 79bd430e08b9e8612194d9b02504f8f4acd889f6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 01:10:26 +0100 Subject: [PATCH 33/45] Remove the mock inventory service for tests and just use the real one all the time with an in-memory data plugin --- .../Tests/Common/Mock/MockInventoryService.cs | 186 ------------------ .../Tests/Common/Setup/SceneSetupHelpers.cs | 19 +- 2 files changed, 6 insertions(+), 199 deletions(-) delete mode 100644 OpenSim/Tests/Common/Mock/MockInventoryService.cs diff --git a/OpenSim/Tests/Common/Mock/MockInventoryService.cs b/OpenSim/Tests/Common/Mock/MockInventoryService.cs deleted file mode 100644 index 4ac1078795..0000000000 --- a/OpenSim/Tests/Common/Mock/MockInventoryService.cs +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using OpenSim.Framework; -using OpenMetaverse; -using OpenSim.Services.Interfaces; -using Nini.Config; - -namespace OpenSim.Tests.Common.Mock -{ - public class MockInventoryService : IInventoryService - { - public MockInventoryService() {} - - public MockInventoryService(IConfigSource config) {} - - /// - /// - /// - /// - /// - public bool CreateUserInventory(UUID userId) - { - return false; - } - - /// - /// - /// - /// - /// - public List GetInventorySkeleton(UUID userId) - { - List folders = new List(); - InventoryFolderBase folder = new InventoryFolderBase(); - folder.ID = UUID.Random(); - folder.Owner = userId; - folders.Add(folder); - return folders; - } - - public InventoryFolderBase GetRootFolder(UUID userID) - { - return new InventoryFolderBase(); - } - - public InventoryCollection GetFolderContent(UUID userID, UUID folderID) - { - return null; - } - - public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) - { - return null; - } - - /// - /// Returns a list of all the active gestures in a user's inventory. - /// - /// - /// The of the user - /// - /// - /// A flat list of the gesture items. - /// - public List GetActiveGestures(UUID userId) - { - return null; - } - - public InventoryCollection GetUserInventory(UUID userID) - { - return null; - } - - public void GetUserInventory(UUID userID, OpenSim.Services.Interfaces.InventoryReceiptCallback callback) - { - } - - public List GetFolderItems(UUID userID, UUID folderID) - { - return null; - } - - public bool AddFolder(InventoryFolderBase folder) - { - return false; - } - - public bool UpdateFolder(InventoryFolderBase folder) - { - return false; - } - - public bool MoveFolder(InventoryFolderBase folder) - { - return false; - } - - public bool DeleteFolders(UUID ownerID, List ids) - { - return false; - } - - public bool PurgeFolder(InventoryFolderBase folder) - { - return false; - } - - public bool AddItem(InventoryItemBase item) - { - return true; - } - - public bool UpdateItem(InventoryItemBase item) - { - return false; - } - - public bool MoveItems(UUID ownerID, List items) - { - return false; - } - - public bool DeleteItems(UUID ownerID, List itemIDs) - { - return false; - } - - public InventoryItemBase GetItem(InventoryItemBase item) - { - return null; - } - - public InventoryFolderBase GetFolder(InventoryFolderBase folder) - { - return null; - } - - public bool HasInventoryForUser(UUID userID) - { - return false; - } - - public InventoryFolderBase RequestRootFolder(UUID userID) - { - InventoryFolderBase root = new InventoryFolderBase(); - root.ID = UUID.Random(); - root.Owner = userID; - root.ParentID = UUID.Zero; - return root; - } - - public int GetAssetPermissions(UUID userID, UUID assetID) - { - return 1; - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 837f4e235f..97d4acefd0 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -137,7 +137,7 @@ namespace OpenSim.Tests.Common.Setup // For now, always started a 'real' authentication service StartAuthenticationService(testScene, true); - LocalInventoryServicesConnector inventoryService = StartInventoryService(testScene, realServices.Contains("inventory")); + LocalInventoryServicesConnector inventoryService = StartInventoryService(testScene); StartGridService(testScene, true); LocalUserAccountServicesConnector userAccountService = StartUserAccountService(testScene); LocalPresenceServicesConnector presenceService = StartPresenceService(testScene); @@ -208,24 +208,17 @@ namespace OpenSim.Tests.Common.Setup //m_authenticationService = service; } - private static LocalInventoryServicesConnector StartInventoryService(Scene testScene, bool real) + private static LocalInventoryServicesConnector StartInventoryService(Scene testScene) { LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); - IConfigSource config = new IniConfigSource(); + + IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("InventoryService"); config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); - - if (real) - { - config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); - } - else - { - config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:MockInventoryService"); - } - + config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); + inventoryService.Initialise(config); inventoryService.AddRegion(testScene); inventoryService.RegionLoaded(testScene); From 54e885581989ddfaf525753ede12c4d4d797cba0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 01:23:26 +0100 Subject: [PATCH 34/45] remove mock asset service for tests in favour of always using the real one --- .../Scenes/Tests/UuidGathererTests.cs | 4 +- OpenSim/Tests/Common/Mock/MockAssetService.cs | 123 ------------------ .../Tests/Common/Setup/SceneSetupHelpers.cs | 14 +- 3 files changed, 8 insertions(+), 133 deletions(-) delete mode 100644 OpenSim/Tests/Common/Mock/MockAssetService.cs diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs index 6b70865533..dbf9e0f550 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs @@ -47,7 +47,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests [SetUp] public void Init() { - m_assetService = new MockAssetService(); + // FIXME: We don't need a full scene here - it would be enough to set up the asset service. + Scene scene = SceneSetupHelpers.SetupScene(); + m_assetService = scene.AssetService; m_uuidGatherer = new UuidGatherer(m_assetService); } diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs deleted file mode 100644 index 9d7c5e29e6..0000000000 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Data; -using OpenSim.Services.Interfaces; -using Nini.Config; - -namespace OpenSim.Tests.Common.Mock -{ - public class MockAssetService : IAssetService - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private readonly Dictionary Assets = new Dictionary(); - - public MockAssetService() {} - - /// - /// This constructor is required if the asset service is being created reflectively (which is the case in some - /// tests). - /// - /// - public MockAssetService(IConfigSource config) {} - - public AssetBase Get(string id) - { -// m_log.DebugFormat("[MOCK ASSET SERVICE]: Getting asset with id {0}", id); - - AssetBase asset; - if (Assets.ContainsKey(id)) - { - asset = Assets[id]; -// m_log.DebugFormat( -// "[MOCK ASSET SERVICE]: Got asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); - } - else - { - asset = null; - } - - return asset; - } - - public AssetBase GetCached(string id) - { - return Get(id); - } - - public AssetMetadata GetMetadata(string id) - { - throw new System.NotImplementedException(); - } - - public byte[] GetData(string id) - { -// m_log.DebugFormat("[MOCK ASSET SERVICE]: Requesting data for asset {0}", id); - - AssetBase asset = Get(id); - - if (asset == null) - return null; - else - return asset.Data; - } - - public bool Get(string id, object sender, AssetRetrieved handler) - { - handler(id, sender, Get(id)); - - return true; - } - - public string Store(AssetBase asset) - { -// m_log.DebugFormat( -// "[MOCK ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.ID, asset.Data.Length); - - Assets[asset.ID] = asset; - - return asset.ID; - } - - public bool UpdateContent(string id, byte[] data) - { - throw new System.NotImplementedException(); - } - - public bool Delete(string id) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 97d4acefd0..484a97dc87 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -132,7 +132,7 @@ namespace OpenSim.Tests.Common.Setup testScene.AddModule(godsModule.Name, godsModule); realServices = realServices.ToLower(); - LocalAssetServicesConnector assetService = StartAssetService(testScene, realServices.Contains("asset")); + LocalAssetServicesConnector assetService = StartAssetService(testScene); // For now, always started a 'real' authentication service StartAuthenticationService(testScene, true); @@ -164,19 +164,15 @@ namespace OpenSim.Tests.Common.Setup return testScene; } - private static LocalAssetServicesConnector StartAssetService(Scene testScene, bool real) + private static LocalAssetServicesConnector StartAssetService(Scene testScene) { LocalAssetServicesConnector assetService = new LocalAssetServicesConnector(); IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - + config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); config.AddConfig("AssetService"); - if (real) - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - else - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:MockAssetService"); - + config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); assetService.Initialise(config); From ba73df39a3824a91ffc848d9b6dc2356d1b307cf Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 01:26:07 +0100 Subject: [PATCH 35/45] remove any reference to a mock authentication service since it doesn't exist and we don't use it --- .../Tests/Common/Setup/SceneSetupHelpers.cs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 484a97dc87..b819581254 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -132,11 +132,8 @@ namespace OpenSim.Tests.Common.Setup testScene.AddModule(godsModule.Name, godsModule); realServices = realServices.ToLower(); - LocalAssetServicesConnector assetService = StartAssetService(testScene); - - // For now, always started a 'real' authentication service - StartAuthenticationService(testScene, true); - + LocalAssetServicesConnector assetService = StartAssetService(testScene); + StartAuthenticationService(testScene); LocalInventoryServicesConnector inventoryService = StartInventoryService(testScene); StartGridService(testScene, true); LocalUserAccountServicesConnector userAccountService = StartUserAccountService(testScene); @@ -183,20 +180,18 @@ namespace OpenSim.Tests.Common.Setup return assetService; } - private static void StartAuthenticationService(Scene testScene, bool real) + private static void StartAuthenticationService(Scene testScene) { ISharedRegionModule service = new LocalAuthenticationServicesConnector(); IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); config.AddConfig("AuthenticationService"); config.Configs["Modules"].Set("AuthenticationServices", "LocalAuthenticationServicesConnector"); - if (real) - config.Configs["AuthenticationService"].Set( - "LocalServiceModule", "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"); - else - config.Configs["AuthenticationService"].Set( - "LocalServiceModule", "OpenSim.Tests.Common.dll:MockAuthenticationService"); + config.Configs["AuthenticationService"].Set( + "LocalServiceModule", "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"); config.Configs["AuthenticationService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); + service.Initialise(config); service.AddRegion(testScene); service.RegionLoaded(testScene); From 631654a38d2ace833f8cd2dc3b6b3860352f8b13 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 01:30:49 +0100 Subject: [PATCH 36/45] remove old code for a mock grid service, which got removed some time back --- OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index b819581254..5d08764a30 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -135,7 +135,7 @@ namespace OpenSim.Tests.Common.Setup LocalAssetServicesConnector assetService = StartAssetService(testScene); StartAuthenticationService(testScene); LocalInventoryServicesConnector inventoryService = StartInventoryService(testScene); - StartGridService(testScene, true); + StartGridService(testScene); LocalUserAccountServicesConnector userAccountService = StartUserAccountService(testScene); LocalPresenceServicesConnector presenceService = StartPresenceService(testScene); @@ -218,24 +218,19 @@ namespace OpenSim.Tests.Common.Setup return inventoryService; } - private static LocalGridServicesConnector StartGridService(Scene testScene, bool real) + private static LocalGridServicesConnector StartGridService(Scene testScene) { IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("GridService"); config.Configs["Modules"].Set("GridServices", "LocalGridServicesConnector"); config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullRegionData"); - if (real) - config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); + config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); LocalGridServicesConnector gridService = new LocalGridServicesConnector(); gridService.Initialise(config); - - //else - // config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:TestGridService"); gridService.AddRegion(testScene); gridService.RegionLoaded(testScene); - //testScene.AddRegionModule(m_gridService.Name, m_gridService); return gridService; } From 66a62678e5da89b0fa004eca3a370d202c239884 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 01:37:27 +0100 Subject: [PATCH 37/45] get rid of all traces of the now used mock service infrastructure --- .../Tests/InventoryArchiveTestCase.cs | 2 +- .../Archiver/Tests/InventoryArchiverTests.cs | 2 +- .../Inventory/Archiver/Tests/PathTests.cs | 14 ++++---- .../Tests/InventoryAccessModuleTests.cs | 2 +- .../World/Serialiser/Tests/SerialiserTests.cs | 2 +- .../Scenes/Tests/StandaloneTeleportTests.cs | 4 +-- .../Scenes/Tests/TaskInventoryTests.cs | 4 +-- .../Tests/Common/Setup/SceneSetupHelpers.cs | 32 ++----------------- 8 files changed, 17 insertions(+), 45 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index e2316f0bdd..5ba08ee094 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // log4net.Config.XmlConfigurator.Configure(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule); UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 69c5dcdab1..d03f6da295 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); m_archiverModule = new InventoryArchiverModule(); - m_scene = SceneSetupHelpers.SetupScene("asset inventory"); + m_scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 0e8f647dbc..c7dae5276b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule); // Create user @@ -180,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests InventoryArchiverModule archiverModule = new InventoryArchiverModule(); // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); @@ -223,7 +223,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "password"); @@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule); // Create user @@ -327,7 +327,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); Dictionary foldersCreated = new Dictionary(); @@ -394,7 +394,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); //log4net.Config.XmlConfigurator.Configure(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); string folder1ExistingName = "a"; @@ -445,7 +445,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); string folder1ExistingName = "a"; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 7a7a8c23f7..8d53cf1542 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests config.AddConfig("Modules"); config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - m_scene = SceneSetupHelpers.SetupScene("Inventory"); + m_scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(m_scene, config, m_iam); // Create user diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index dafaa0c107..a866fd938c 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -237,7 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests public void Init() { m_serialiserModule = new SerialiserModule(); - m_scene = SceneSetupHelpers.SetupScene(""); + m_scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(m_scene, m_serialiserModule); } diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs index 8588f7f599..dd28416788 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs @@ -117,11 +117,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); - Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010, "grid"); + Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010); SceneSetupHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms); sceneB.RegisterRegionWithGrid(); - Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000, "grid"); + Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000); SceneSetupHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms); sceneA.RegisterRegionWithGrid(); diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 8138bcc19a..2aef4b0d19 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -101,7 +101,7 @@ namespace OpenSim.Region.Framework.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); UserAccount user1 = CreateUser(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; @@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); + Scene scene = SceneSetupHelpers.SetupScene(); UserAccount user1 = CreateUser(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 5d08764a30..99517d2b19 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -66,32 +66,7 @@ namespace OpenSim.Tests.Common.Setup /// public static TestScene SetupScene() { - return SetupScene(""); - } - - /// - /// Set up a test scene - /// - /// - /// Starts real inventory and asset services, as opposed to mock ones, if true - /// - public static TestScene SetupScene(String realServices) - { - return SetupScene("Unit test region", UUID.Random(), 1000, 1000, realServices); - } - - /// - /// Set up a test scene - /// - /// Name of the region - /// ID of the region - /// X co-ordinate of the region - /// Y co-ordinate of the region - /// This should be the same if simulating two scenes within a standalone - /// - public static TestScene SetupScene(string name, UUID id, uint x, uint y) - { - return SetupScene(name, id, x, y, ""); + return SetupScene("Unit test region", UUID.Random(), 1000, 1000); } /// @@ -103,10 +78,8 @@ namespace OpenSim.Tests.Common.Setup /// X co-ordinate of the region /// Y co-ordinate of the region /// This should be the same if simulating two scenes within a standalone - /// Starts real inventory and asset services, as opposed to mock ones, if true /// - public static TestScene SetupScene( - string name, UUID id, uint x, uint y, String realServices) + public static TestScene SetupScene(string name, UUID id, uint x, uint y) { Console.WriteLine("Setting up test scene {0}", name); @@ -130,7 +103,6 @@ namespace OpenSim.Tests.Common.Setup IRegionModule godsModule = new GodsModule(); godsModule.Initialise(testScene, new IniConfigSource()); testScene.AddModule(godsModule.Name, godsModule); - realServices = realServices.ToLower(); LocalAssetServicesConnector assetService = StartAssetService(testScene); StartAuthenticationService(testScene); From 40bf417da7705711f33c64b82611203ff2a0adad Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 13 Apr 2011 16:10:18 -0400 Subject: [PATCH 38/45] Add ColladaMesh switch --- .../CoreModules/Avatar/Assets/GetMeshModule.cs | 13 +++++++++++-- .../NewFileAgentInventoryVariablePriceModule.cs | 11 ++++++++++- bin/OpenSimDefaults.ini | 6 +++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs index 878242a447..d2278bc3de 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs @@ -54,6 +54,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets private Scene m_scene; private IAssetService m_assetService; + private bool m_enabled = true; #region IRegionModuleBase Members @@ -65,7 +66,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void Initialise(IConfigSource source) { - + IConfig startupConfig = source.Configs["Startup"]; + if (startupConfig == null) + return; + + if (!startupConfig.GetBoolean("ColladaMesh",true)) + m_enabled = false; } public void AddRegion(Scene pScene) @@ -101,16 +107,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void RegisterCaps(UUID agentID, Caps caps) { + if(!m_enabled) + return; + UUID capID = UUID.Random(); // m_log.Info("[GETMESH]: /CAPS/" + capID); + caps.RegisterHandler("GetMesh", new RestHTTPHandler("GET", "/CAPS/" + capID, delegate(Hashtable m_dhttpMethod) { return ProcessGetMesh(m_dhttpMethod, agentID, caps); })); - } #endregion diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs index 4a42c938d5..fb07cc9ca0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs @@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets private Scene m_scene; // private IAssetService m_assetService; private bool m_dumpAssetsToFile = false; + private bool m_enabled = true; #region IRegionModuleBase Members @@ -67,7 +68,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void Initialise(IConfigSource source) { - + IConfig startupConfig = source.Configs["Startup"]; + if (startupConfig == null) + return; + + if (!startupConfig.GetBoolean("ColladaMesh",true)) + m_enabled = false; } public void AddRegion(Scene pScene) @@ -103,6 +109,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void RegisterCaps(UUID agentID, Caps caps) { + if(!m_enabled) + return; + UUID capID = UUID.Random(); // m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID); diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index f857b8da63..107e859827 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -154,7 +154,11 @@ ; mesh, and use it for collisions. This is currently experimental code and enabling ; it may cause unexpected physics problems. ;UseMeshiesPhysicsMesh = false - + + ; enable / disable Collada mesh support + ; default is true + ; ColladaMesh = true + ; 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 From 52d92303926c8be46af734707274e6d8ecd70602 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 22:47:47 +0100 Subject: [PATCH 39/45] refactor: split out some rez code into a separate CreateItemForObject() method --- .../InventoryAccess/InventoryAccessModule.cs | 302 +++++++++--------- 1 file changed, 159 insertions(+), 143 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index c0946f4d52..0f2b9a68c2 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -274,154 +274,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectGroup objectGroup in objlist) objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; - // Get the user info of the item destination - // - UUID userID = UUID.Zero; - - if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || - action == DeRezAction.SaveToExistingUserInventoryItem) - { - // Take or take copy require a taker - // Saving changes requires a local user - // - if (remoteClient == null) - return UUID.Zero; - - userID = remoteClient.AgentId; - } - else - { - // All returns / deletes go to the object owner - // - userID = objlist[0].RootPart.OwnerID; - } - - if (userID == UUID.Zero) // Can't proceed - { + InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); + if (item == null) return UUID.Zero; - } - - // If we're returning someone's item, it goes back to the - // owner's Lost And Found folder. - // Delete is treated like return in this case - // Deleting your own items makes them go to trash - // - - InventoryFolderBase folder = null; - InventoryItemBase item = null; - - if (DeRezAction.SaveToExistingUserInventoryItem == action) + + // Can't know creator is the same, so null it in inventory + if (objlist.Count > 1) { - item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID); - item = m_Scene.InventoryService.GetItem(item); - - //item = userInfo.RootFolder.FindItem( - // objectGroup.RootPart.FromUserInventoryItemID); - - if (null == item) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", - objlist[0].Name, objlist[0].UUID); - return UUID.Zero; - } + item.CreatorId = UUID.Zero.ToString(); + item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; } else { - // Folder magic - // - if (action == DeRezAction.Delete) - { - // Deleting someone else's item - // - if (remoteClient == null || - objlist[0].OwnerID != remoteClient.AgentId) - { - - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); - } - else - { - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); - } - } - else if (action == DeRezAction.Return) - { - - // Dump to lost + found unconditionally - // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); - } - - if (folderID == UUID.Zero && folder == null) - { - if (action == DeRezAction.Delete) - { - // Deletes go to trash by default - // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); - } - else - { - if (remoteClient == null || - objlist[0].OwnerID != remoteClient.AgentId) - { - // Taking copy of another person's item. Take to - // Objects folder. - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); - } - else - { - // Catch all. Use lost & found - // - - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); - } - } - } - - // Override and put into where it came from, if it came - // from anywhere in inventory - // - if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) - { - if (objlist[0].RootPart.FromFolderID != UUID.Zero) - { - InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID); - folder = m_Scene.InventoryService.GetFolder(f); - } - } - - if (folder == null) // None of the above - { - folder = new InventoryFolderBase(folderID); - - if (folder == null) // Nowhere to put it - { - return UUID.Zero; - } - } - - item = new InventoryItemBase(); - // Can't know creator is the same, so null it in inventory - if (objlist.Count > 1) - item.CreatorId = UUID.Zero.ToString(); - else - item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); - item.ID = UUID.Random(); - item.InvType = (int)InventoryType.Object; - item.Folder = folder.ID; - item.Owner = userID; - if (objlist.Count > 1) - { - item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; - } - else - { - item.SaleType = objlist[0].RootPart.ObjectSaleType; - item.SalePrice = objlist[0].RootPart.SalePrice; - } - } + item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); + item.SaleType = objlist[0].RootPart.ObjectSaleType; + item.SalePrice = objlist[0].RootPart.SalePrice; + } AssetBase asset = CreateAsset( objlist[0].GetPartName(objlist[0].RootPart.LocalId), @@ -505,8 +373,156 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } } + return assetID; } + + /// + /// Create an item using details for the given scene object. + /// + /// + /// + /// + /// + /// + protected InventoryItemBase CreateItemForObject( + DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) + { + // Get the user info of the item destination + // + UUID userID = UUID.Zero; + + if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || + action == DeRezAction.SaveToExistingUserInventoryItem) + { + // Take or take copy require a taker + // Saving changes requires a local user + // + if (remoteClient == null) + return null; + + userID = remoteClient.AgentId; + } + else + { + // All returns / deletes go to the object owner + // + userID = so.RootPart.OwnerID; + } + + if (userID == UUID.Zero) // Can't proceed + { + return null; + } + + // If we're returning someone's item, it goes back to the + // owner's Lost And Found folder. + // Delete is treated like return in this case + // Deleting your own items makes them go to trash + // + + InventoryFolderBase folder = null; + InventoryItemBase item = null; + + if (DeRezAction.SaveToExistingUserInventoryItem == action) + { + item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); + item = m_Scene.InventoryService.GetItem(item); + + //item = userInfo.RootFolder.FindItem( + // objectGroup.RootPart.FromUserInventoryItemID); + + if (null == item) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", + so.Name, so.UUID); + + return null; + } + } + else + { + // Folder magic + // + if (action == DeRezAction.Delete) + { + // Deleting someone else's item + // + if (remoteClient == null || + so.OwnerID != remoteClient.AgentId) + { + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + } + else + { + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); + } + } + else if (action == DeRezAction.Return) + { + // Dump to lost + found unconditionally + // + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + } + + if (folderID == UUID.Zero && folder == null) + { + if (action == DeRezAction.Delete) + { + // Deletes go to trash by default + // + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); + } + else + { + if (remoteClient == null || so.OwnerID != remoteClient.AgentId) + { + // Taking copy of another person's item. Take to + // Objects folder. + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); + } + else + { + // Catch all. Use lost & found + // + + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + } + } + } + + // Override and put into where it came from, if it came + // from anywhere in inventory + // + if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) + { + if (so.RootPart.FromFolderID != UUID.Zero) + { + InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); + folder = m_Scene.InventoryService.GetFolder(f); + } + } + + if (folder == null) // None of the above + { + folder = new InventoryFolderBase(folderID); + + if (folder == null) // Nowhere to put it + { + return null; + } + } + + item = new InventoryItemBase(); + item.ID = UUID.Random(); + item.InvType = (int)InventoryType.Object; + item.Folder = folder.ID; + item.Owner = userID; + } + + return item; + } /// /// Rez an object into the scene from the user's inventory From 9c7f14bf366eaa113ca7a89d3b40a42529e7726e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 23:07:23 +0100 Subject: [PATCH 40/45] minor: remove a small amount of code duplication --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 0f2b9a68c2..5d1902502f 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -298,17 +298,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess Utils.StringToBytes(itemXml), objlist[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); - assetID = asset.FullID; + + item.AssetID = asset.FullID; + assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { - item.AssetID = asset.FullID; m_Scene.InventoryService.UpdateItem(item); } else { - item.AssetID = asset.FullID; - uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; foreach (SceneObjectGroup grp in objlist) effectivePerms &= grp.GetEffectivePermissions(); From fc365f2a31d46b9c6517159330c7f6953eb60e9f Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 15 Apr 2011 18:23:37 -0400 Subject: [PATCH 41/45] Thanks Snoopy for a patch that allows setting of perms on items given to new avatars --- .../RemoteController/RemoteAdminPlugin.cs | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 1b4d1ea9f9..c6b34f9f20 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -1587,6 +1587,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController { InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); destinationItem.Name = item.Name; + destinationItem.Owner = destination; destinationItem.Description = item.Description; destinationItem.InvType = item.InvType; destinationItem.CreatorId = item.CreatorId; @@ -1606,6 +1607,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController destinationItem.Flags = item.Flags; destinationItem.CreationDate = item.CreationDate; destinationItem.Folder = destinationFolder.ID; + ApplyNextOwnerPermissions(destinationItem); m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); @@ -1640,6 +1642,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController { InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); destinationItem.Name = item.Name; + destinationItem.Owner = destination; destinationItem.Description = item.Description; destinationItem.InvType = item.InvType; destinationItem.CreatorId = item.CreatorId; @@ -1659,6 +1662,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController destinationItem.Flags = item.Flags; destinationItem.CreationDate = item.CreationDate; destinationItem.Folder = destinationFolder.ID; + ApplyNextOwnerPermissions(destinationItem); m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); @@ -1716,7 +1720,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController { destinationFolder = new InventoryFolderBase(); destinationFolder.ID = UUID.Random(); - destinationFolder.Name = assetType.ToString(); + if (assetType == AssetType.Clothing) { + destinationFolder.Name = "Clothing"; + } else { + destinationFolder.Name = "Body Parts"; + } destinationFolder.Owner = destination; destinationFolder.Type = (short)assetType; destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; @@ -1748,6 +1756,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController { InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); destinationItem.Name = item.Name; + destinationItem.Owner = destination; destinationItem.Description = item.Description; destinationItem.InvType = item.InvType; destinationItem.CreatorId = item.CreatorId; @@ -1767,6 +1776,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController destinationItem.Flags = item.Flags; destinationItem.CreationDate = item.CreationDate; destinationItem.Folder = extraFolder.ID; + ApplyNextOwnerPermissions(destinationItem); m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); inventoryMap.Add(item.ID, destinationItem.ID); @@ -1783,6 +1793,29 @@ namespace OpenSim.ApplicationPlugins.RemoteController } } + /// + /// Apply next owner permissions. + /// + + private void ApplyNextOwnerPermissions(InventoryItemBase item) + { + if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) + { + if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Copy; + if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; + if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Modify; + } + item.CurrentPermissions &= item.NextPermissions; + item.BasePermissions &= item.NextPermissions; + item.EveryOnePermissions &= item.NextPermissions; + // item.OwnerChanged = true; + // item.PermsMask = 0; + // item.PermsGranter = UUID.Zero; + } + /// /// This method is called if a given model avatar name can not be found. If the external /// file has already been loaded once, then control returns immediately. If not, then it From 1dba671f45b691bcf024e9ffd5568e8a7ea2165c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 23:32:46 +0100 Subject: [PATCH 42/45] refactor: separate out code that adds permissions --- .../InventoryAccess/InventoryAccessModule.cs | 101 ++++++++++-------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 5d1902502f..8b68dbe64a 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -308,48 +308,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } else { - uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; - foreach (SceneObjectGroup grp in objlist) - effectivePerms &= grp.GetEffectivePermissions(); - effectivePerms |= (uint)PermissionMask.Move; - - if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) - { - uint perms = effectivePerms; - uint nextPerms = (perms & 7) << 13; - if ((nextPerms & (uint)PermissionMask.Copy) == 0) - perms &= ~(uint)PermissionMask.Copy; - if ((nextPerms & (uint)PermissionMask.Transfer) == 0) - perms &= ~(uint)PermissionMask.Transfer; - if ((nextPerms & (uint)PermissionMask.Modify) == 0) - perms &= ~(uint)PermissionMask.Modify; - - item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask; - item.CurrentPermissions = item.BasePermissions; - item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask; - item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask; - item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask; - - // Magic number badness. Maybe this deserves an enum. - // bit 4 (16) is the "Slam" bit, it means treat as passed - // and apply next owner perms on rez - item.CurrentPermissions |= 16; // Slam! - } - else - { - item.BasePermissions = effectivePerms; - item.CurrentPermissions = effectivePerms; - item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms; - item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms; - item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms; - - item.CurrentPermissions &= - ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify | - (uint)PermissionMask.Move | - 7); // Preserve folded permissions - } + AddPermissions(item, objlist[0], objlist, remoteClient); item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; @@ -376,6 +335,64 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return assetID; } + /// + /// Add relevant permissions for an object to the item. + /// + /// + /// + /// + /// + /// + protected InventoryItemBase AddPermissions( + InventoryItemBase item, SceneObjectGroup so, List objsForEffectivePermissions, + IClientAPI remoteClient) + { + uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; + foreach (SceneObjectGroup grp in objsForEffectivePermissions) + effectivePerms &= grp.GetEffectivePermissions(); + effectivePerms |= (uint)PermissionMask.Move; + + if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) + { + uint perms = effectivePerms; + uint nextPerms = (perms & 7) << 13; + if ((nextPerms & (uint)PermissionMask.Copy) == 0) + perms &= ~(uint)PermissionMask.Copy; + if ((nextPerms & (uint)PermissionMask.Transfer) == 0) + perms &= ~(uint)PermissionMask.Transfer; + if ((nextPerms & (uint)PermissionMask.Modify) == 0) + perms &= ~(uint)PermissionMask.Modify; + + item.BasePermissions = perms & so.RootPart.NextOwnerMask; + item.CurrentPermissions = item.BasePermissions; + item.NextPermissions = perms & so.RootPart.NextOwnerMask; + item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask; + item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask; + + // Magic number badness. Maybe this deserves an enum. + // bit 4 (16) is the "Slam" bit, it means treat as passed + // and apply next owner perms on rez + item.CurrentPermissions |= 16; // Slam! + } + else + { + item.BasePermissions = effectivePerms; + item.CurrentPermissions = effectivePerms; + item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms; + item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms; + item.GroupPermissions = so.RootPart.GroupMask & effectivePerms; + + item.CurrentPermissions &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify | + (uint)PermissionMask.Move | + 7); // Preserve folded permissions + } + + return item; + } + /// /// Create an item using details for the given scene object. /// From ed74be65995afe192ce03177325c98b0100ab157 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 15 Apr 2011 23:54:30 +0100 Subject: [PATCH 43/45] Make remote admin error messages more helpful on windows. Also, make log messages conform more with convention. --- .../RemoteController/RemoteAdminPlugin.cs | 161 ++++++++---------- 1 file changed, 73 insertions(+), 88 deletions(-) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index c6b34f9f20..dc4309fbe2 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -94,7 +94,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController public void Initialise() { - m_log.Info("[RADMIN]: " + Name + " cannot be default-initialized!"); + m_log.Error("[RADMIN]: " + Name + " cannot be default-initialized!"); throw new PluginNotInitialisedException(Name); } @@ -111,7 +111,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController else { m_config = m_configSource.Configs["RemoteAdmin"]; - m_log.Info("[RADMIN]: Remote Admin Plugin Enabled"); + m_log.Debug("[RADMIN]: Remote Admin Plugin Enabled"); m_requiredPassword = m_config.GetString("access_password", String.Empty); int port = m_config.GetInt("port", 0); @@ -230,8 +230,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN]: Restart region: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); responseData["accepted"] = false; responseData["success"] = false; responseData["rebooting"] = false; @@ -277,8 +276,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN]: Broadcasting: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message, e.StackTrace); responseData["accepted"] = false; responseData["success"] = false; @@ -301,7 +299,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable) request.Params[0]; - m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}", request.ToString()); + m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}", request); // foreach (string k in requestData.Keys) // { // m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}: >{1}< {2}", @@ -348,8 +346,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN]: Terrain Loading: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN]: Terrain Loading: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: Terrain Loading: failed: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -417,14 +414,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] Shutdown: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN] Shutdown: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: Shutdown: failed: {0} {1}", e.Message, e.StackTrace); responseData["accepted"] = false; responseData["error"] = e.Message; response.Value = responseData; } + m_log.Info("[RADMIN]: Shutdown Administrator Request complete"); return response; } @@ -725,8 +722,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] CreateRegion: failed {0}", e.Message); - m_log.DebugFormat("[RADMIN] CreateRegion: failed {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN] CreateRegion: failed {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -792,8 +788,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] DeleteRegion: failed {0}", e.Message); - m_log.DebugFormat("[RADMIN] DeleteRegion: failed {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN] DeleteRegion: failed {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -884,8 +879,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] CloseRegion: failed {0}", e.Message); - m_log.DebugFormat("[RADMIN] CloseRegion: failed {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: CloseRegion: failed {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -982,8 +976,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] ModifyRegion: failed {0}", e.Message); - m_log.DebugFormat("[RADMIN] ModifyRegion: failed {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN] ModifyRegion: failed {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -1106,8 +1099,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] CreateUser: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN] CreateUser: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: CreateUser: failed: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["avatar_uuid"] = UUID.Zero.ToString(); @@ -1198,8 +1190,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] UserExists: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN] UserExists: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: UserExists: failed: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -1372,9 +1363,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - - m_log.ErrorFormat("[RADMIN] UpdateUserAccount: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN] UpdateUserAccount: failed: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN] UpdateUserAccount: failed: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["avatar_uuid"] = UUID.Zero.ToString(); @@ -1382,6 +1371,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController response.Value = responseData; } + m_log.Info("[RADMIN]: UpdateUserAccount: request complete"); return response; } @@ -1397,7 +1387,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController private void UpdateUserAppearance(Hashtable responseData, Hashtable requestData, UUID userid) { - m_log.DebugFormat("[RADMIN] updateUserAppearance"); + m_log.DebugFormat("[RADMIN]: updateUserAppearance"); string defaultMale = m_config.GetString("default_male", "Default Male"); string defaultFemale = m_config.GetString("default_female", "Default Female"); @@ -1437,16 +1427,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (String.IsNullOrEmpty(model)) { - m_log.DebugFormat("[RADMIN] Appearance update not requested"); + m_log.DebugFormat("[RADMIN]: Appearance update not requested"); return; } - m_log.DebugFormat("[RADMIN] Setting appearance for avatar {0}, using model <{1}>", userid, model); + m_log.DebugFormat("[RADMIN]: Setting appearance for avatar {0}, using model <{1}>", userid, model); string[] modelSpecifiers = model.Split(); if (modelSpecifiers.Length != 2) { - m_log.WarnFormat("[RADMIN] User appearance not set for {0}. Invalid model name : <{1}>", userid, model); + m_log.WarnFormat("[RADMIN]: User appearance not set for {0}. Invalid model name : <{1}>", userid, model); // modelSpecifiers = dmodel.Split(); return; } @@ -1457,7 +1447,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (modelProfile == null) { - m_log.WarnFormat("[RADMIN] Requested model ({0}) not found. Appearance unchanged", model); + m_log.WarnFormat("[RADMIN]: Requested model ({0}) not found. Appearance unchanged", model); return; } @@ -1467,7 +1457,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController EstablishAppearance(userid, modelProfile.PrincipalID); - m_log.DebugFormat("[RADMIN] Finished setting appearance for avatar {0}, using model {1}", + m_log.DebugFormat("[RADMIN]: Finished setting appearance for avatar {0}, using model {1}", userid, model); } @@ -1479,7 +1469,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController private void EstablishAppearance(UUID destination, UUID source) { - m_log.DebugFormat("[RADMIN] Initializing inventory for {0} from {1}", destination, source); + m_log.DebugFormat("[RADMIN]: Initializing inventory for {0} from {1}", destination, source); Scene scene = m_application.SceneManager.CurrentOrFirstScene; // If the model has no associated appearance we're done. @@ -1501,7 +1491,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.WarnFormat("[RADMIN] Error transferring appearance for {0} : {1}", + m_log.WarnFormat("[RADMIN]: Error transferring appearance for {0} : {1}", destination, e.Message); } @@ -1532,7 +1522,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.WarnFormat("[RADMIN] Error transferring appearance for {0} : {1}", + m_log.WarnFormat("[RADMIN]: Error transferring appearance for {0} : {1}", destination, e.Message); } @@ -1567,7 +1557,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; destinationFolder.Version = 1; inventoryService.AddFolder(destinationFolder); // store base record - m_log.ErrorFormat("[RADMIN] Created folder for destination {0}", source); + m_log.ErrorFormat("[RADMIN]: Created folder for destination {0}", source); } // Wearables @@ -1730,7 +1720,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; destinationFolder.Version = 1; inventoryService.AddFolder(destinationFolder); // store base record - m_log.ErrorFormat("[RADMIN] Created folder for destination {0}", source); + m_log.ErrorFormat("[RADMIN]: Created folder for destination {0}", source); } InventoryFolderBase extraFolder; @@ -1748,7 +1738,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController extraFolder.ParentID = destinationFolder.ID; inventoryService.AddFolder(extraFolder); - m_log.DebugFormat("[RADMIN] Added folder {0} to folder {1}", extraFolder.ID, sourceFolder.ID); + m_log.DebugFormat("[RADMIN]: Added folder {0} to folder {1}", extraFolder.ID, sourceFolder.ID); List items = inventoryService.GetFolderContent(source, folder.ID).Items; @@ -1825,7 +1815,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// indicate which outfit is the default, and this outfit will be automatically worn. The /// other outfits are provided to allow "real" avatars a way to easily change their outfits. /// - private bool CreateDefaultAvatars() { // Only load once @@ -1834,7 +1823,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController return false; } - m_log.DebugFormat("[RADMIN] Creating default avatar entries"); + m_log.DebugFormat("[RADMIN]: Creating default avatar entries"); m_defaultAvatarsLoaded = true; @@ -1890,7 +1879,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController foreach (XmlElement avatar in avatars) { - m_log.DebugFormat("[RADMIN] Loading appearance for {0}, gender = {1}", + m_log.DebugFormat("[RADMIN]: Loading appearance for {0}, gender = {1}", GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?")); // Create the user identified by the avatar entry @@ -1912,7 +1901,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController account = CreateUser(scopeID, names[0], names[1], password, email); if (null == account) { - m_log.ErrorFormat("[RADMIN] Avatar {0} {1} was not created", names[0], names[1]); + m_log.ErrorFormat("[RADMIN]: Avatar {0} {1} was not created", names[0], names[1]); return false; } } @@ -1930,12 +1919,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController ID = account.PrincipalID; - m_log.DebugFormat("[RADMIN] User {0}[{1}] created or retrieved", name, ID); + m_log.DebugFormat("[RADMIN]: User {0}[{1}] created or retrieved", name, ID); include = true; } catch (Exception e) { - m_log.DebugFormat("[RADMIN] Error creating user {0} : {1}", name, e.Message); + m_log.DebugFormat("[RADMIN]: Error creating user {0} : {1}", name, e.Message); include = false; } @@ -1975,7 +1964,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController clothingFolder.ParentID = inventoryService.GetRootFolder(ID).ID; clothingFolder.Version = 1; inventoryService.AddFolder(clothingFolder); // store base record - m_log.ErrorFormat("[RADMIN] Created clothing folder for {0}/{1}", name, ID); + m_log.ErrorFormat("[RADMIN]: Created clothing folder for {0}/{1}", name, ID); } // OK, now we have an inventory for the user, read in the outfits from the @@ -1988,7 +1977,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController foreach (XmlElement outfit in outfits) { - m_log.DebugFormat("[RADMIN] Loading outfit {0} for {1}", + m_log.DebugFormat("[RADMIN]: Loading outfit {0} for {1}", GetStringAttribute(outfit,"name","?"), GetStringAttribute(avatar,"name","?")); outfitName = GetStringAttribute(outfit,"name",""); @@ -2012,7 +2001,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController // Otherwise, we must create the folder. if (extraFolder == null) { - m_log.DebugFormat("[RADMIN] Creating outfit folder {0} for {1}", outfitName, name); + m_log.DebugFormat("[RADMIN]: Creating outfit folder {0} for {1}", outfitName, name); extraFolder = new InventoryFolderBase(); extraFolder.ID = UUID.Random(); extraFolder.Name = outfitName; @@ -2021,7 +2010,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController extraFolder.Version = 1; extraFolder.ParentID = clothingFolder.ID; inventoryService.AddFolder(extraFolder); - m_log.DebugFormat("[RADMIN] Adding outfile folder {0} to folder {1}", extraFolder.ID, clothingFolder.ID); + m_log.DebugFormat("[RADMIN]: Adding outfile folder {0} to folder {1}", extraFolder.ID, clothingFolder.ID); } // Now get the pieces that make up the outfit @@ -2036,7 +2025,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController switch (child.Name) { case "Permissions" : - m_log.DebugFormat("[RADMIN] Permissions specified"); + m_log.DebugFormat("[RADMIN]: Permissions specified"); perms = child; break; case "Asset" : @@ -2086,7 +2075,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController inventoryItem.Folder = extraFolder.ID; // Parent folder m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(inventoryItem); - m_log.DebugFormat("[RADMIN] Added item {0} to folder {1}", inventoryItem.ID, extraFolder.ID); + m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", inventoryItem.ID, extraFolder.ID); } // Attach item, if attachpoint is specified @@ -2094,7 +2083,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (attachpoint != 0) { avatarAppearance.SetAttachment(attachpoint, inventoryItem.ID, inventoryItem.AssetID); - m_log.DebugFormat("[RADMIN] Attached {0}", inventoryItem.ID); + m_log.DebugFormat("[RADMIN]: Attached {0}", inventoryItem.ID); } // Record whether or not the item is to be initially worn @@ -2107,32 +2096,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.WarnFormat("[RADMIN] Error wearing item {0} : {1}", inventoryItem.ID, e.Message); + m_log.WarnFormat("[RADMIN]: Error wearing item {0} : {1}", inventoryItem.ID, e.Message); } } // foreach item in outfit - m_log.DebugFormat("[RADMIN] Outfit {0} load completed", outfitName); + m_log.DebugFormat("[RADMIN]: Outfit {0} load completed", outfitName); } // foreach outfit - m_log.DebugFormat("[RADMIN] Inventory update complete for {0}", name); + m_log.DebugFormat("[RADMIN]: Inventory update complete for {0}", name); scene.AvatarService.SetAppearance(ID, avatarAppearance); } catch (Exception e) { - m_log.WarnFormat("[RADMIN] Inventory processing incomplete for user {0} : {1}", + m_log.WarnFormat("[RADMIN]: Inventory processing incomplete for user {0} : {1}", name, e.Message); } } // End of include } - m_log.DebugFormat("[RADMIN] Default avatar loading complete"); + m_log.DebugFormat("[RADMIN]: Default avatar loading complete"); } else { - m_log.DebugFormat("[RADMIN] No default avatar information available"); + m_log.DebugFormat("[RADMIN]: No default avatar information available"); return false; } } catch (Exception e) { - m_log.WarnFormat("[RADMIN] Exception whilst loading default avatars ; {0}", e.Message); + m_log.WarnFormat("[RADMIN]: Exception whilst loading default avatars ; {0}", e.Message); return false; } @@ -2227,8 +2216,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] LoadOAR: {0}", e.Message); - m_log.DebugFormat("[RADMIN] LoadOAR: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: LoadOAR: {0} {1}", e.Message, e.StackTrace); responseData["loaded"] = false; responseData["error"] = e.Message; @@ -2333,8 +2321,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] SaveOAR: {0}", e.Message); - m_log.DebugFormat("[RADMIN] SaveOAR: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: SaveOAR: {0} {1}", e.Message, e.StackTrace); responseData["saved"] = false; responseData["error"] = e.Message; @@ -2348,7 +2335,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController private void RemoteAdminOarSaveCompleted(Guid uuid, string name) { - m_log.DebugFormat("[RADMIN] File processing complete for {0}", name); + m_log.DebugFormat("[RADMIN]: File processing complete for {0}", name); lock (m_saveOarLock) Monitor.Pulse(m_saveOarLock); } @@ -2386,14 +2373,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2424,8 +2411,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] LoadXml: {0}", e.Message); - m_log.DebugFormat("[RADMIN] LoadXml: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN] LoadXml: {0} {1}", e.Message, e.StackTrace); responseData["loaded"] = false; responseData["switched"] = false; @@ -2471,14 +2457,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2510,8 +2496,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] SaveXml: {0}", e.Message); - m_log.DebugFormat("[RADMIN] SaveXml: {0}", e.ToString()); + m_log.ErrorFormat("[RADMIN]: SaveXml: {0} {1}", e.Message, e.StackTrace); responseData["saved"] = false; responseData["switched"] = false; @@ -2550,14 +2535,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2569,7 +2554,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] RegionQuery: {0}", e.Message); + m_log.InfoFormat("[RADMIN]: RegionQuery: {0}", e.Message); responseData["success"] = false; responseData["error"] = e.Message; @@ -2610,7 +2595,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] ConsoleCommand: {0}", e.Message); + m_log.InfoFormat("[RADMIN]: ConsoleCommand: {0}", e.Message); responseData["success"] = false; responseData["error"] = e.Message; @@ -2647,14 +2632,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2665,7 +2650,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] Access List Clear Request: {0}", e.Message); + m_log.ErrorFormat("[RADMIN]: Access List Clear Request: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -2704,14 +2689,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2731,7 +2716,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (account != null) { uuids.Add(account.PrincipalID); - m_log.DebugFormat("[RADMIN] adding \"{0}\" to ACL for \"{1}\"", name, scene.RegionInfo.RegionName); + m_log.DebugFormat("[RADMIN]: adding \"{0}\" to ACL for \"{1}\"", name, scene.RegionInfo.RegionName); } } List accessControlList = new List(scene.RegionInfo.EstateSettings.EstateAccess); @@ -2752,7 +2737,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] Access List Add Request: {0}", e.Message); + m_log.ErrorFormat("[RADMIN]: Access List Add Request: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -2791,14 +2776,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2839,7 +2824,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] Access List Remove Request: {0}", e.Message); + m_log.ErrorFormat("[RADMIN]: Access List Remove Request: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; @@ -2878,14 +2863,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) { string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2907,7 +2892,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { - m_log.InfoFormat("[RADMIN] Acces List List: {0}", e.Message); + m_log.ErrorFormat("[RADMIN]: Access List List: {0} {1}", e.Message, e.StackTrace); responseData["success"] = false; responseData["error"] = e.Message; From cd6dce11086a4e8a06257659c19eaa66d3b1a951 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 15 Apr 2011 16:42:40 -0700 Subject: [PATCH 44/45] Fixes mantis #5431 -- coalesced objects in HG-enabled regions. Needs more testing to make sure HG inventory isn't broken by this (it shouldn't). --- .../HGInventoryAccessModule.cs | 27 +++---------------- .../InventoryAccess/InventoryAccessModule.cs | 10 ++++++- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 4565d103ff..8c99983a95 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -129,35 +129,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } /// - /// DeleteToInventory + /// Used in DeleteToInventory /// - public override UUID DeleteToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient) + protected override void ExportAsset(UUID agentID, UUID assetID) { - UUID ret = UUID.Zero; - - // HACK: Only works for lists of length one. - // Intermediate version, just to make things compile - foreach (SceneObjectGroup g in objectGroups) - ret = DeleteToInventory(action, folderID, g, remoteClient); - - return ret; - } - - // DO NOT OVERRIDE THE BASE METHOD - public new virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, - SceneObjectGroup objectGroup, IClientAPI remoteClient) - { - UUID assetID = base.DeleteToInventory(action, folderID, new List() {objectGroup}, remoteClient); - if (!assetID.Equals(UUID.Zero)) - { - if (remoteClient != null) - UploadInventoryItem(remoteClient.AgentId, assetID, "", 0); - } + UploadInventoryItem(agentID, assetID, "", 0); else m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); - - return assetID; } /// diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 8b68dbe64a..a716326924 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -330,11 +330,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } } + + // This is a hook to do some per-asset post-processing for subclasses that need that + ExportAsset(remoteClient.AgentId, assetID); } return assetID; } - + + protected virtual void ExportAsset(UUID agentID, UUID assetID) + { + // nothing to do here + } + /// /// Add relevant permissions for an object to the item. /// From 70084c5e3a34e681357baf5506bd0c8f9815049b Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Sat, 16 Apr 2011 15:29:28 -0700 Subject: [PATCH 45/45] More descriptive debug msg for ServiceOSDRequest failures. --- OpenSim/Framework/WebUtil.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 64cd014f5c..9d70f63189 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -222,8 +222,8 @@ namespace OpenSim.Framework m_log.InfoFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", reqnum,url,method,tickdiff,tickdata); } - - m_log.WarnFormat("[WEB UTIL] <{0}> osd request failed: {1}",reqnum,errorMessage); + + m_log.WarnFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); return ErrorResponseMap(errorMessage); }