aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorRobert Adams2014-01-21 11:31:51 -0800
committerRobert Adams2014-01-21 11:31:51 -0800
commit4c362a83f9ce0b168ea96ba7dbd7ec012445ecff (patch)
tree7f03a860379fb2c6905d78a6616db762c86dd634 /OpenSim/Region
parentvarregion: remove debugging splat file saving that fills up the (diff)
parentAdds a configuration option to cannibalize bandwidth from the (diff)
downloadopensim-SC_OLD-4c362a83f9ce0b168ea96ba7dbd7ec012445ecff.zip
opensim-SC_OLD-4c362a83f9ce0b168ea96ba7dbd7ec012445ecff.tar.gz
opensim-SC_OLD-4c362a83f9ce0b168ea96ba7dbd7ec012445ecff.tar.bz2
opensim-SC_OLD-4c362a83f9ce0b168ea96ba7dbd7ec012445ecff.tar.xz
Merge branch 'master' into varregion
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs14
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs6
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs81
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs657
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs590
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs41
20 files changed, 1133 insertions, 733 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 202cc62..51433cb 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -162,6 +162,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
162 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 162 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
163 private int m_maxRTO = 60000; 163 private int m_maxRTO = 60000;
164 164
165 /// <summary>
166 /// This is the percentage of the udp texture queue to add to the task queue since
167 /// textures are now generally handled through http.
168 /// </summary>
169 private double m_cannibalrate = 0.0;
170
165 private ClientInfo m_info = new ClientInfo(); 171 private ClientInfo m_info = new ClientInfo();
166 172
167 /// <summary> 173 /// <summary>
@@ -201,6 +207,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
201 // Create an array of token buckets for this clients different throttle categories 207 // Create an array of token buckets for this clients different throttle categories
202 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 208 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
203 209
210 m_cannibalrate = rates.CannibalizeTextureRate;
211
204 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 212 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
205 { 213 {
206 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 214 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
@@ -349,6 +357,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
349 texture = Math.Max(texture, LLUDPServer.MTU); 357 texture = Math.Max(texture, LLUDPServer.MTU);
350 asset = Math.Max(asset, LLUDPServer.MTU); 358 asset = Math.Max(asset, LLUDPServer.MTU);
351 359
360 // Since most textures are now delivered through http, make it possible
361 // to cannibalize some of the bw from the texture throttle to use for
362 // the task queue (e.g. object updates)
363 task = task + (int)(m_cannibalrate * texture);
364 texture = (int)((1 - m_cannibalrate) * texture);
365
352 //int total = resend + land + wind + cloud + task + texture + asset; 366 //int total = resend + land + wind + cloud + task + texture + asset;
353 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", 367 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
354 // AgentID, resend, land, wind, cloud, task, texture, asset, total); 368 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index c9aac0b..e5bae6e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -59,6 +59,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// <summary>Flag used to enable adaptive throttles</summary> 59 /// <summary>Flag used to enable adaptive throttles</summary>
60 public bool AdaptiveThrottlesEnabled; 60 public bool AdaptiveThrottlesEnabled;
61 61
62 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
63 public double CannibalizeTextureRate;
64
62 /// <summary> 65 /// <summary>
63 /// Default constructor 66 /// Default constructor
64 /// </summary> 67 /// </summary>
@@ -80,6 +83,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 83 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
81 84
82 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 85 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
86
87 CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
88 CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
83 } 89 }
84 catch (Exception) { } 90 catch (Exception) { }
85 } 91 }
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 6a5f8f3..b270de9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -771,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Asset
771 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 771 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
772 772
773 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 773 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
774 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 774 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
775 775
776 foreach (Scene s in m_Scenes) 776 foreach (Scene s in m_Scenes)
777 { 777 {
@@ -794,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Asset
794 else if (storeUncached) 794 else if (storeUncached)
795 { 795 {
796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
797 if (cachedAsset == null && assets[assetID] != AssetType.Unknown) 797 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
798 m_log.DebugFormat( 798 m_log.DebugFormat(
799 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", 799 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); 800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 4ec8ae7..4292719 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 /// <value> 78 /// <value>
79 /// Used to collect the uuids of the assets that we need to save into the archive 79 /// Used to collect the uuids of the assets that we need to save into the archive
80 /// </value> 80 /// </value>
81 protected Dictionary<UUID, AssetType> m_assetUuids = new Dictionary<UUID, AssetType>(); 81 protected Dictionary<UUID, sbyte> m_assetUuids = new Dictionary<UUID, sbyte>();
82 82
83 /// <value> 83 /// <value>
84 /// Used to collect the uuids of the users that we need to save into the archive 84 /// Used to collect the uuids of the users that we need to save into the archive
@@ -187,7 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
187 187
188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset 188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) 189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); 190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (sbyte)inventoryItem.AssetType, m_assetUuids);
191 } 191 }
192 192
193 /// <summary> 193 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 04a0db6..09b1975 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -182,11 +182,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
182 { 182 {
183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); 184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
185 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 185 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url); 186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
187 uuidGatherer.GatherAssetUuids(so, ids); 187 uuidGatherer.GatherAssetUuids(so, ids);
188 188
189 foreach (KeyValuePair<UUID, AssetType> kvp in ids) 189 foreach (KeyValuePair<UUID, sbyte> kvp in ids)
190 uuidGatherer.FetchAsset(kvp.Key); 190 uuidGatherer.FetchAsset(kvp.Key);
191 } 191 }
192 } 192 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index b7a4d1a..d4fb1ba 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -260,9 +260,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
260 260
261 // The act of gathering UUIDs downloads some assets from the remote server 261 // The act of gathering UUIDs downloads some assets from the remote server
262 // but not all... 262 // but not all...
263 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 263 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); 264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
265 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); 265 uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
266 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); 266 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
267 bool success = true; 267 bool success = true;
268 foreach (UUID uuid in ids.Keys) 268 foreach (UUID uuid in ids.Keys)
@@ -286,9 +286,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
287 if (asset != null) 287 if (asset != null)
288 { 288 {
289 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 289 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
291 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 291 uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
292 bool success = false; 292 bool success = false;
293 foreach (UUID uuid in ids.Keys) 293 foreach (UUID uuid in ids.Keys)
294 { 294 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index 9f39aa2..cd95ee9 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
178 178
179 // Archive the regions 179 // Archive the regions
180 180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); 181 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
182 182
183 scenesGroup.ForEachScene(delegate(Scene scene) 183 scenesGroup.ForEachScene(delegate(Scene scene)
184 { 184 {
@@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 216 }
217 } 217 }
218 218
219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids)
220 { 220 {
221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
222 222
@@ -276,16 +276,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings; 276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
277 277
278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) 278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
279 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; 279 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
280 280
281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) 281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
282 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; 282 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
283 283
284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) 284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
285 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; 285 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
286 286
287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) 287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
288 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; 288 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
289 289
290 Save(scene, sceneObjects, regionDir); 290 Save(scene, sceneObjects, regionDir);
291 } 291 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 9600023..2d0da61 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
81 /// <value> 81 /// <value>
82 /// uuids to request 82 /// uuids to request
83 /// </value> 83 /// </value>
84 protected IDictionary<UUID, AssetType> m_uuids; 84 protected IDictionary<UUID, sbyte> m_uuids;
85 85
86 /// <value> 86 /// <value>
87 /// Callback used when all the assets requested have been received. 87 /// Callback used when all the assets requested have been received.
@@ -115,7 +115,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
115 protected Dictionary<string, object> m_options; 115 protected Dictionary<string, object> m_options;
116 116
117 protected internal AssetsRequest( 117 protected internal AssetsRequest(
118 AssetsArchiver assetsArchiver, IDictionary<UUID, AssetType> uuids, 118 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
119 IAssetService assetService, IUserAccountService userService, 119 IAssetService assetService, IUserAccountService userService,
120 UUID scope, Dictionary<string, object> options, 120 UUID scope, Dictionary<string, object> options,
121 AssetsRequestCallback assetsRequestCallback) 121 AssetsRequestCallback assetsRequestCallback)
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
154 154
155 m_requestCallbackTimer.Enabled = true; 155 m_requestCallbackTimer.Enabled = true;
156 156
157 foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) 157 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
158 { 158 {
159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
160 160
@@ -235,9 +235,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer 235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) 236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
237 { 237 {
238 AssetType type = (AssetType)assetType; 238 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, type); 239 fetchedAsset.Type = (sbyte)assetType;
240 fetchedAsset.Type = (sbyte)type;
241 } 240 }
242 241
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 242 AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 173b603..1659493 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
60 60
61 public void Initialise() 61 public void Initialise()
62 { 62 {
63 m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName); 63// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName);
64 64
65 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture", 65 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture",
66 "set terrain texture <number> <uuid> [<x>] [<y>]", 66 "set terrain texture <number> <uuid> [<x>] [<y>]",
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 17387da..3bd7b4a 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -702,7 +702,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
702 } 702 }
703 } 703 }
704 704
705 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 705 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
706 { 706 {
707 SceneObjectPart part; 707 SceneObjectPart part;
708 708
@@ -742,7 +742,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
742 default: 742 default:
743 break; 743 break;
744 } 744 }
745 SendTelehubInfo(client); 745
746 if (client != null)
747 SendTelehubInfo(client);
746 } 748 }
747 749
748 private void SendSimulatorBlueBoxMessage( 750 private void SendSimulatorBlueBoxMessage(
@@ -1214,7 +1216,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1214 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; 1216 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest;
1215 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; 1217 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest;
1216 client.OnEstateChangeInfo += handleEstateChangeInfo; 1218 client.OnEstateChangeInfo += handleEstateChangeInfo;
1217 client.OnEstateManageTelehub += handleOnEstateManageTelehub; 1219 client.OnEstateManageTelehub += HandleOnEstateManageTelehub;
1218 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; 1220 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest;
1219 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; 1221 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
1220 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; 1222 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index b67312e..1a89721 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -51,10 +51,17 @@ namespace OpenSim.Region.Framework.Interfaces
51 UUID = 5 51 UUID = 5
52 } 52 }
53 53
54 public struct JsonStoreStats
55 {
56 public int StoreCount;
57 }
58
54 public delegate void TakeValueCallback(string s); 59 public delegate void TakeValueCallback(string s);
55 60
56 public interface IJsonStoreModule 61 public interface IJsonStoreModule
57 { 62 {
63 JsonStoreStats GetStoreStats();
64
58 bool AttachObjectStore(UUID objectID); 65 bool AttachObjectStore(UUID objectID);
59 bool CreateStore(string value, ref UUID result); 66 bool CreateStore(string value, ref UUID result);
60 bool DestroyStore(UUID storeID); 67 bool DestroyStore(UUID storeID);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index aee621f..2f666c0 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3930,32 +3930,52 @@ namespace OpenSim.Region.Framework.Scenes
3930 } 3930 }
3931 } 3931 }
3932 3932
3933// m_log.DebugFormat(
3934// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
3935// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
3936
3933 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 3937 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
3934 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 3938 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
3935 RegionInfo.EstateSettings.AllowDirectTeleport == false && 3939 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
3936 !viahome && !godlike) 3940 !viahome && !godlike)
3937 { 3941 {
3938 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 3942 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
3939 // Can have multiple SpawnPoints 3943
3940 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 3944 if (telehub != null)
3941 if (spawnpoints.Count > 1)
3942 { 3945 {
3943 // We have multiple SpawnPoints, Route the agent to a random or sequential one 3946 // Can have multiple SpawnPoints
3944 if (SpawnPointRouting == "random") 3947 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
3945 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 3948 if (spawnpoints.Count > 1)
3946 telehub.AbsolutePosition, 3949 {
3947 telehub.GroupRotation 3950 // We have multiple SpawnPoints, Route the agent to a random or sequential one
3948 ); 3951 if (SpawnPointRouting == "random")
3952 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
3953 telehub.AbsolutePosition,
3954 telehub.GroupRotation
3955 );
3956 else
3957 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
3958 telehub.AbsolutePosition,
3959 telehub.GroupRotation
3960 );
3961 }
3962 else if (spawnpoints.Count == 1)
3963 {
3964 // We have a single SpawnPoint and will route the agent to it
3965 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
3966 }
3949 else 3967 else
3950 acd.startpos = spawnpoints[SpawnPoint()].GetLocation( 3968 {
3951 telehub.AbsolutePosition, 3969 m_log.DebugFormat(
3952 telehub.GroupRotation 3970 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
3953 ); 3971 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
3972 }
3954 } 3973 }
3955 else 3974 else
3956 { 3975 {
3957 // We have a single SpawnPoint and will route the agent to it 3976 m_log.DebugFormat(
3958 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 3977 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
3978 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
3959 } 3979 }
3960 3980
3961 return true; 3981 return true;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
new file mode 100644
index 0000000..9a97acc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
@@ -0,0 +1,119 @@
1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are met:
4 * * Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer.
6 * * Redistributions in binary form must reproduce the above copyright
7 * notice, this list of conditions and the following disclaimer in the
8 * documentation and/or other materials provided with the distribution.
9 * * Neither the name of the OpenSimulator Project nor the
10 * names of its contributors may be used to endorse or promote products
11 * derived from this software without specific prior written permission.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25using System;
26using Nini.Config;
27using NUnit.Framework;
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.CoreModules.World.Estate;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Services.Interfaces;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.Framework.Scenes.Tests
38{
39 /// <summary>
40 /// Scene telehub tests
41 /// </summary>
42 /// <remarks>
43 /// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour
44 /// in the case of an error condition
45 /// </remarks>
46 [TestFixture]
47 public class SceneTelehubTests : OpenSimTestCase
48 {
49 /// <summary>
50 /// Test for desired behaviour when a telehub has no spawn points
51 /// </summary>
52 [Test]
53 public void TestNoTelehubSpawnPoints()
54 {
55 TestHelpers.InMethod();
56// TestHelpers.EnableLogging();
57
58 EstateManagementModule emm = new EstateManagementModule();
59
60 SceneHelpers sh = new SceneHelpers();
61 Scene scene = sh.SetupScene();
62 SceneHelpers.SetupSceneModules(scene, emm);
63
64 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
65
66 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
67
68 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
69 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
70
71 // Must still be possible to successfully log in
72 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
73
74 UserAccount ua
75 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
76
77 SceneHelpers.AddScenePresence(scene, ua);
78
79 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
80 }
81
82 /// <summary>
83 /// Test for desired behaviour when the scene object nominated as a telehub object does not exist.
84 /// </summary>
85 [Test]
86 public void TestNoTelehubSceneObject()
87 {
88 TestHelpers.InMethod();
89// TestHelpers.EnableLogging();
90
91 EstateManagementModule emm = new EstateManagementModule();
92
93 SceneHelpers sh = new SceneHelpers();
94 Scene scene = sh.SetupScene();
95 SceneHelpers.SetupSceneModules(scene, emm);
96
97 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
98
99 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
100 SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner);
101
102 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
103 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId);
104 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
105
106 scene.DeleteSceneObject(telehubSo, false);
107
108 // Must still be possible to successfully log in
109 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
110
111 UserAccount ua
112 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
113
114 SceneHelpers.AddScenePresence(scene, ua);
115
116 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
117 }
118 }
119} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 3e074b9..75a51b5 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -38,6 +38,7 @@ using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
41 42
42namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
43{ 44{
@@ -83,7 +84,7 @@ namespace OpenSim.Region.Framework.Scenes
83 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
84 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
85 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
86 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
87 { 88 {
88 // avoid infinite loops 89 // avoid infinite loops
89 if (assetUuids.ContainsKey(assetUuid)) 90 if (assetUuids.ContainsKey(assetUuid))
@@ -93,23 +94,27 @@ namespace OpenSim.Region.Framework.Scenes
93 { 94 {
94 assetUuids[assetUuid] = assetType; 95 assetUuids[assetUuid] = assetType;
95 96
96 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 97 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
97 { 98 {
98 GetWearableAssetUuids(assetUuid, assetUuids); 99 GetWearableAssetUuids(assetUuid, assetUuids);
99 } 100 }
100 else if (AssetType.Gesture == assetType) 101 else if ((sbyte)AssetType.Gesture == assetType)
101 { 102 {
102 GetGestureAssetUuids(assetUuid, assetUuids); 103 GetGestureAssetUuids(assetUuid, assetUuids);
103 } 104 }
104 else if (AssetType.Notecard == assetType) 105 else if ((sbyte)AssetType.Notecard == assetType)
105 { 106 {
106 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
107 } 108 }
108 else if (AssetType.LSLText == assetType) 109 else if ((sbyte)AssetType.LSLText == assetType)
109 { 110 {
110 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 111 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
111 } 112 }
112 else if (AssetType.Object == assetType) 113 else if ((sbyte)OpenSimAssetType.Material == assetType)
114 {
115 GetMaterialAssetUuids(assetUuid, assetUuids);
116 }
117 else if ((sbyte)AssetType.Object == assetType)
113 { 118 {
114 GetSceneObjectAssetUuids(assetUuid, assetUuids); 119 GetSceneObjectAssetUuids(assetUuid, assetUuids);
115 } 120 }
@@ -136,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes
136 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 141 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
137 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. 142 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
138 /// </param> 143 /// </param>
139 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 144 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
140 { 145 {
141// m_log.DebugFormat( 146// m_log.DebugFormat(
142// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 147// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -156,7 +161,7 @@ namespace OpenSim.Region.Framework.Scenes
156 { 161 {
157 // Get the prim's default texture. This will be used for faces which don't have their own texture 162 // Get the prim's default texture. This will be used for faces which don't have their own texture
158 if (textureEntry.DefaultTexture != null) 163 if (textureEntry.DefaultTexture != null)
159 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 164 assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
160 165
161 if (textureEntry.FaceTextures != null) 166 if (textureEntry.FaceTextures != null)
162 { 167 {
@@ -164,20 +169,20 @@ namespace OpenSim.Region.Framework.Scenes
164 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 169 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
165 { 170 {
166 if (texture != null) 171 if (texture != null)
167 assetUuids[texture.TextureID] = AssetType.Texture; 172 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
168 } 173 }
169 } 174 }
170 } 175 }
171 176
172 // If the prim is a sculpt then preserve this information too 177 // If the prim is a sculpt then preserve this information too
173 if (part.Shape.SculptTexture != UUID.Zero) 178 if (part.Shape.SculptTexture != UUID.Zero)
174 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 179 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
175 180
176 if (part.Shape.ProjectionTextureUUID != UUID.Zero) 181 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
177 assetUuids[part.Shape.ProjectionTextureUUID] = AssetType.Texture; 182 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
178 183
179 if (part.CollisionSound != UUID.Zero) 184 if (part.CollisionSound != UUID.Zero)
180 assetUuids[part.CollisionSound] = AssetType.Sound; 185 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
181 186
182 if (part.ParticleSystem.Length > 0) 187 if (part.ParticleSystem.Length > 0)
183 { 188 {
@@ -185,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes
185 { 190 {
186 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); 191 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
187 if (ps.Texture != UUID.Zero) 192 if (ps.Texture != UUID.Zero)
188 assetUuids[ps.Texture] = AssetType.Texture; 193 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
189 } 194 }
190 catch (Exception e) 195 catch (Exception e)
191 { 196 {
@@ -205,7 +210,7 @@ namespace OpenSim.Region.Framework.Scenes
205// tii.Name, tii.Type, part.Name, part.UUID); 210// tii.Name, tii.Type, part.Name, part.UUID);
206 211
207 if (!assetUuids.ContainsKey(tii.AssetID)) 212 if (!assetUuids.ContainsKey(tii.AssetID))
208 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 213 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
209 } 214 }
210 215
211 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed 216 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
@@ -214,7 +219,9 @@ namespace OpenSim.Region.Framework.Scenes
214 // Scene.EventManager is present. 219 // Scene.EventManager is present.
215// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); 220// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
216 221
217 GatherMaterialsUuids(part, assetUuids); 222
223 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
224 GatherMaterialsUuids(part, assetUuids);
218 } 225 }
219 catch (Exception e) 226 catch (Exception e)
220 { 227 {
@@ -225,7 +232,7 @@ namespace OpenSim.Region.Framework.Scenes
225 } 232 }
226 } 233 }
227 } 234 }
228 235
229// /// <summary> 236// /// <summary>
230// /// The callback made when we request the asset for an object from the asset service. 237// /// The callback made when we request the asset for an object from the asset service.
231// /// </summary> 238// /// </summary>
@@ -241,10 +248,12 @@ namespace OpenSim.Region.Framework.Scenes
241 248
242 /// <summary> 249 /// <summary>
243 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps 250 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
251 /// stored in legacy format in part.DynAttrs
244 /// </summary> 252 /// </summary>
245 /// <param name="part"></param> 253 /// <param name="part"></param>
246 /// <param name="assetUuids"></param> 254 /// <param name="assetUuids"></param>
247 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids) 255 //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
256 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
248 { 257 {
249 // scan thru the dynAttrs map of this part for any textures used as materials 258 // scan thru the dynAttrs map of this part for any textures used as materials
250 OSD osdMaterials = null; 259 OSD osdMaterials = null;
@@ -280,7 +289,7 @@ namespace OpenSim.Region.Framework.Scenes
280 UUID normalMapId = mat["NormMap"].AsUUID(); 289 UUID normalMapId = mat["NormMap"].AsUUID();
281 if (normalMapId != UUID.Zero) 290 if (normalMapId != UUID.Zero)
282 { 291 {
283 assetUuids[normalMapId] = AssetType.Texture; 292 assetUuids[normalMapId] = (sbyte)AssetType.Texture;
284 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); 293 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
285 } 294 }
286 } 295 }
@@ -289,7 +298,7 @@ namespace OpenSim.Region.Framework.Scenes
289 UUID specularMapId = mat["SpecMap"].AsUUID(); 298 UUID specularMapId = mat["SpecMap"].AsUUID();
290 if (specularMapId != UUID.Zero) 299 if (specularMapId != UUID.Zero)
291 { 300 {
292 assetUuids[specularMapId] = AssetType.Texture; 301 assetUuids[specularMapId] = (sbyte)AssetType.Texture;
293 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); 302 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
294 } 303 }
295 } 304 }
@@ -344,7 +353,7 @@ namespace OpenSim.Region.Framework.Scenes
344 /// </summary> 353 /// </summary>
345 /// <param name="scriptUuid"></param> 354 /// <param name="scriptUuid"></param>
346 /// <param name="assetUuids">Dictionary in which to record the references</param> 355 /// <param name="assetUuids">Dictionary in which to record the references</param>
347 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 356 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
348 { 357 {
349// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 358// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
350 359
@@ -364,7 +373,7 @@ namespace OpenSim.Region.Framework.Scenes
364 373
365 // Embedded asset references (if not false positives) could be for many types of asset, so we will 374 // Embedded asset references (if not false positives) could be for many types of asset, so we will
366 // label these as unknown. 375 // label these as unknown.
367 assetUuids[uuid] = AssetType.Unknown; 376 assetUuids[uuid] = (sbyte)AssetType.Unknown;
368 } 377 }
369 } 378 }
370 } 379 }
@@ -374,7 +383,7 @@ namespace OpenSim.Region.Framework.Scenes
374 /// </summary> 383 /// </summary>
375 /// <param name="wearableAssetUuid"></param> 384 /// <param name="wearableAssetUuid"></param>
376 /// <param name="assetUuids">Dictionary in which to record the references</param> 385 /// <param name="assetUuids">Dictionary in which to record the references</param>
377 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 386 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
378 { 387 {
379 AssetBase assetBase = GetAsset(wearableAssetUuid); 388 AssetBase assetBase = GetAsset(wearableAssetUuid);
380 389
@@ -389,7 +398,7 @@ namespace OpenSim.Region.Framework.Scenes
389 398
390 foreach (UUID uuid in wearableAsset.Textures.Values) 399 foreach (UUID uuid in wearableAsset.Textures.Values)
391 { 400 {
392 assetUuids[uuid] = AssetType.Texture; 401 assetUuids[uuid] = (sbyte)AssetType.Texture;
393 } 402 }
394 } 403 }
395 } 404 }
@@ -401,7 +410,7 @@ namespace OpenSim.Region.Framework.Scenes
401 /// </summary> 410 /// </summary>
402 /// <param name="sceneObject"></param> 411 /// <param name="sceneObject"></param>
403 /// <param name="assetUuids"></param> 412 /// <param name="assetUuids"></param>
404 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 413 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
405 { 414 {
406 AssetBase objectAsset = GetAsset(sceneObjectUuid); 415 AssetBase objectAsset = GetAsset(sceneObjectUuid);
407 416
@@ -430,7 +439,7 @@ namespace OpenSim.Region.Framework.Scenes
430 /// </summary> 439 /// </summary>
431 /// <param name="gestureUuid"></param> 440 /// <param name="gestureUuid"></param>
432 /// <param name="assetUuids"></param> 441 /// <param name="assetUuids"></param>
433 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 442 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
434 { 443 {
435 AssetBase assetBase = GetAsset(gestureUuid); 444 AssetBase assetBase = GetAsset(gestureUuid);
436 if (null == assetBase) 445 if (null == assetBase)
@@ -464,9 +473,29 @@ namespace OpenSim.Region.Framework.Scenes
464 // If it can be parsed as a UUID, it is an asset ID 473 // If it can be parsed as a UUID, it is an asset ID
465 UUID uuid; 474 UUID uuid;
466 if (UUID.TryParse(id, out uuid)) 475 if (UUID.TryParse(id, out uuid))
467 assetUuids[uuid] = AssetType.Animation; 476 assetUuids[uuid] = (sbyte)AssetType.Animation;
468 } 477 }
469 } 478 }
479
480 /// <summary>
481 /// Get the asset uuid's referenced in a material.
482 /// </summary>
483 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
484 {
485 AssetBase assetBase = GetAsset(materialUuid);
486 if (null == assetBase)
487 return;
488
489 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
490
491 UUID normMap = mat["NormMap"].AsUUID();
492 if (normMap != UUID.Zero)
493 assetUuids[normMap] = (sbyte)AssetType.Texture;
494
495 UUID specMap = mat["SpecMap"].AsUUID();
496 if (specMap != UUID.Zero)
497 assetUuids[specMap] = (sbyte)AssetType.Texture;
498 }
470 } 499 }
471 500
472 public class HGUuidGatherer : UuidGatherer 501 public class HGUuidGatherer : UuidGatherer
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs
deleted file mode 100644
index d8f5563..0000000
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsDemoModule.cs
+++ /dev/null
@@ -1,657 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Security.Cryptography; // for computing md5 hash
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using Ionic.Zlib;
47
48// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
49// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
50// the available DLLs
51//[assembly: Addin("MaterialsDemoModule", "1.0")]
52//[assembly: AddinDependency("OpenSim", "0.5")]
53
54namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
55{
56 /// <summary>
57 ///
58 // # # ## ##### # # # # # ####
59 // # # # # # # ## # # ## # # #
60 // # # # # # # # # # # # # # #
61 // # ## # ###### ##### # # # # # # # # ###
62 // ## ## # # # # # ## # # ## # #
63 // # # # # # # # # # # # ####
64 //
65 // THIS MODULE IS FOR EXPERIMENTAL USE ONLY AND MAY CAUSE REGION OR ASSET CORRUPTION!
66 //
67 ////////////// WARNING //////////////////////////////////////////////////////////////////
68 /// This is an *Experimental* module for developing support for materials-capable viewers
69 /// This module should NOT be used in a production environment! It may cause data corruption and
70 /// viewer crashes. It should be only used to evaluate implementations of materials.
71 ///
72 /// Materials are persisted via SceneObjectPart.dynattrs. This is a relatively new feature
73 /// of OpenSimulator and is not field proven at the time this module was written. Persistence
74 /// may fail or become corrupt and this could cause viewer crashes due to erroneous materials
75 /// data being sent to viewers. Materials descriptions might survive IAR, OAR, or other means
76 /// of archiving however the texture resources used by these materials probably will not as they
77 /// may not be adequately referenced to ensure proper archiving.
78 ///
79 ///
80 ///
81 /// To enable this module, add this string at the bottom of OpenSim.ini:
82 /// [MaterialsDemoModule]
83 ///
84 /// </summary>
85 ///
86
87 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
88 public class MaterialsDemoModule : INonSharedRegionModule
89 {
90 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
91
92 public string Name { get { return "MaterialsDemoModule"; } }
93
94 public Type ReplaceableInterface { get { return null; } }
95
96 private Scene m_scene = null;
97 private bool m_enabled = false;
98
99 public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>();
100
101 public void Initialise(IConfigSource source)
102 {
103 m_enabled = (source.Configs["MaterialsDemoModule"] != null);
104 if (!m_enabled)
105 return;
106
107 m_log.DebugFormat("[MaterialsDemoModule]: INITIALIZED MODULE");
108 }
109
110 public void Close()
111 {
112 if (!m_enabled)
113 return;
114
115 m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
116 }
117
118 public void AddRegion(Scene scene)
119 {
120 if (!m_enabled)
121 return;
122
123 m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
124
125 m_scene = scene;
126 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
127 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
128// m_scene.EventManager.OnGatherUuids += GatherMaterialsUuids;
129 }
130
131 void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
132 {
133 foreach (var part in obj.Parts)
134 if (part != null)
135 GetStoredMaterialsForPart(part);
136 }
137
138 void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
139 {
140 string capsBase = "/CAPS/" + caps.CapsObjectPath;
141
142 IRequestHandler renderMaterialsPostHandler
143 = new RestStreamHandler("POST", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
144 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
145
146 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
147 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
148 // handler normally and then add a GET handler via MainServer
149
150 IRequestHandler renderMaterialsGetHandler
151 = new RestStreamHandler("GET", capsBase + "/", RenderMaterialsGetCap, "RenderMaterials", null);
152 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
153
154 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
155 IRequestHandler renderMaterialsPutHandler
156 = new RestStreamHandler("PUT", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
157 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
158 }
159
160 public void RemoveRegion(Scene scene)
161 {
162 if (!m_enabled)
163 return;
164
165 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
166 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
167// m_scene.EventManager.OnGatherUuids -= GatherMaterialsUuids;
168
169 m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
170 }
171
172 public void RegionLoaded(Scene scene)
173 {
174 }
175
176 OSDMap GetMaterial(UUID id)
177 {
178 OSDMap map = null;
179 lock (m_knownMaterials)
180 {
181 if (m_knownMaterials.ContainsKey(id))
182 {
183 map = new OSDMap();
184 map["ID"] = OSD.FromBinary(id.GetBytes());
185 map["Material"] = m_knownMaterials[id];
186 }
187 }
188 return map;
189 }
190
191 void GetStoredMaterialsForPart(SceneObjectPart part)
192 {
193 OSD OSMaterials = null;
194 OSDArray matsArr = null;
195
196 if (part.DynAttrs == null)
197 {
198 m_log.Warn("[MaterialsDemoModule]: NULL DYNATTRS :( ");
199 }
200
201 lock (part.DynAttrs)
202 {
203 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
204 {
205 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
206
207 if (materialsStore == null)
208 return;
209
210 materialsStore.TryGetValue("Materials", out OSMaterials);
211 }
212
213 if (OSMaterials != null && OSMaterials is OSDArray)
214 matsArr = OSMaterials as OSDArray;
215 else
216 return;
217 }
218
219 m_log.Info("[MaterialsDemoModule]: OSMaterials: " + OSDParser.SerializeJsonString(OSMaterials));
220
221 if (matsArr == null)
222 {
223 m_log.Info("[MaterialsDemoModule]: matsArr is null :( ");
224 return;
225 }
226
227 foreach (OSD elemOsd in matsArr)
228 {
229 if (elemOsd != null && elemOsd is OSDMap)
230 {
231 OSDMap matMap = elemOsd as OSDMap;
232 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
233 {
234 try
235 {
236 lock (m_knownMaterials)
237 m_knownMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
238 }
239 catch (Exception e)
240 {
241 m_log.Warn("[MaterialsDemoModule]: exception decoding persisted material: " + e.ToString());
242 }
243 }
244 }
245 }
246 }
247
248 void StoreMaterialsForPart(SceneObjectPart part)
249 {
250 try
251 {
252 if (part == null || part.Shape == null)
253 return;
254
255 Dictionary<UUID, OSDMap> mats = new Dictionary<UUID, OSDMap>();
256
257 Primitive.TextureEntry te = part.Shape.Textures;
258
259 if (te.DefaultTexture != null)
260 {
261 lock (m_knownMaterials)
262 {
263 if (m_knownMaterials.ContainsKey(te.DefaultTexture.MaterialID))
264 mats[te.DefaultTexture.MaterialID] = m_knownMaterials[te.DefaultTexture.MaterialID];
265 }
266 }
267
268 if (te.FaceTextures != null)
269 {
270 foreach (var face in te.FaceTextures)
271 {
272 if (face != null)
273 {
274 lock (m_knownMaterials)
275 {
276 if (m_knownMaterials.ContainsKey(face.MaterialID))
277 mats[face.MaterialID] = m_knownMaterials[face.MaterialID];
278 }
279 }
280 }
281 }
282 if (mats.Count == 0)
283 return;
284
285 OSDArray matsArr = new OSDArray();
286 foreach (KeyValuePair<UUID, OSDMap> kvp in mats)
287 {
288 OSDMap matOsd = new OSDMap();
289 matOsd["ID"] = OSD.FromUUID(kvp.Key);
290 matOsd["Material"] = kvp.Value;
291 matsArr.Add(matOsd);
292 }
293
294 OSDMap OSMaterials = new OSDMap();
295 OSMaterials["Materials"] = matsArr;
296
297 lock (part.DynAttrs)
298 part.DynAttrs.SetStore("OpenSim", "Materials", OSMaterials);
299 }
300 catch (Exception e)
301 {
302 m_log.Warn("[MaterialsDemoModule]: exception in StoreMaterialsForPart(): " + e.ToString());
303 }
304 }
305
306 public string RenderMaterialsPostCap(string request, string path,
307 string param, IOSHttpRequest httpRequest,
308 IOSHttpResponse httpResponse)
309 {
310 m_log.Debug("[MaterialsDemoModule]: POST cap handler");
311
312 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
313 OSDMap resp = new OSDMap();
314
315 OSDMap materialsFromViewer = null;
316
317 OSDArray respArr = new OSDArray();
318
319 if (req.ContainsKey("Zipped"))
320 {
321 OSD osd = null;
322
323 byte[] inBytes = req["Zipped"].AsBinary();
324
325 try
326 {
327 osd = ZDecompressBytesToOsd(inBytes);
328
329 if (osd != null)
330 {
331 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
332 {
333 foreach (OSD elem in (OSDArray)osd)
334 {
335
336 try
337 {
338 UUID id = new UUID(elem.AsBinary(), 0);
339
340 lock (m_knownMaterials)
341 {
342 if (m_knownMaterials.ContainsKey(id))
343 {
344 m_log.Info("[MaterialsDemoModule]: request for known material ID: " + id.ToString());
345 OSDMap matMap = new OSDMap();
346 matMap["ID"] = OSD.FromBinary(id.GetBytes());
347
348 matMap["Material"] = m_knownMaterials[id];
349 respArr.Add(matMap);
350 }
351 else
352 m_log.Info("[MaterialsDemoModule]: request for UNKNOWN material ID: " + id.ToString());
353 }
354 }
355 catch (Exception e)
356 {
357 // report something here?
358 continue;
359 }
360 }
361 }
362 else if (osd is OSDMap) // reqest to assign a material
363 {
364 materialsFromViewer = osd as OSDMap;
365
366 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
367 {
368 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
369 if (matsOsd is OSDArray)
370 {
371 OSDArray matsArr = matsOsd as OSDArray;
372
373 try
374 {
375 foreach (OSDMap matsMap in matsArr)
376 {
377 m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
378
379 uint matLocalID = 0;
380 try { matLocalID = matsMap["ID"].AsUInteger(); }
381 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); }
382 m_log.Debug("[MaterialsDemoModule]: matLocalId: " + matLocalID.ToString());
383
384
385 OSDMap mat = null;
386 try { mat = matsMap["Material"] as OSDMap; }
387 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); }
388 m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat));
389
390 UUID id = HashOsd(mat);
391 lock (m_knownMaterials)
392 m_knownMaterials[id] = mat;
393
394
395 var sop = m_scene.GetSceneObjectPart(matLocalID);
396 if (sop == null)
397 m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + matLocalID.ToString());
398 else
399 {
400 var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
401
402 if (te == null)
403 {
404 m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + matLocalID.ToString());
405 }
406 else
407 {
408 int face = -1;
409
410 if (matsMap.ContainsKey("Face"))
411 {
412 face = matsMap["Face"].AsInteger();
413 if (te.FaceTextures == null) // && face == 0)
414 {
415 if (te.DefaultTexture == null)
416 m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
417 else
418 te.DefaultTexture.MaterialID = id;
419 }
420 else
421 {
422 if (te.FaceTextures.Length >= face - 1)
423 {
424 if (te.FaceTextures[face] == null)
425 te.DefaultTexture.MaterialID = id;
426 else
427 te.FaceTextures[face].MaterialID = id;
428 }
429 }
430 }
431 else
432 {
433 if (te.DefaultTexture != null)
434 te.DefaultTexture.MaterialID = id;
435 }
436
437 m_log.Debug("[MaterialsDemoModule]: setting material ID for face " + face.ToString() + " to " + id.ToString());
438
439 //we cant use sop.UpdateTextureEntry(te); because it filters so do it manually
440
441 if (sop.ParentGroup != null)
442 {
443 sop.Shape.TextureEntry = te.GetBytes();
444 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
445 sop.UpdateFlag = UpdateRequired.FULL;
446 sop.ParentGroup.HasGroupChanged = true;
447
448 sop.ScheduleFullUpdate();
449
450 StoreMaterialsForPart(sop);
451 }
452 }
453 }
454 }
455 }
456 catch (Exception e)
457 {
458 m_log.Warn("[MaterialsDemoModule]: exception processing received material: " + e.Message);
459 }
460 }
461 }
462 }
463 }
464
465 }
466 catch (Exception e)
467 {
468 m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload: " + e.Message);
469 //return "";
470 }
471 m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
472 }
473
474
475 resp["Zipped"] = ZCompressOSD(respArr, false);
476 string response = OSDParser.SerializeLLSDXmlString(resp);
477
478 //m_log.Debug("[MaterialsDemoModule]: cap request: " + request);
479 m_log.Debug("[MaterialsDemoModule]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
480 m_log.Debug("[MaterialsDemoModule]: cap response: " + response);
481 return response;
482 }
483
484
485 public string RenderMaterialsGetCap(string request, string path,
486 string param, IOSHttpRequest httpRequest,
487 IOSHttpResponse httpResponse)
488 {
489 m_log.Debug("[MaterialsDemoModule]: GET cap handler");
490
491 OSDMap resp = new OSDMap();
492 int matsCount = 0;
493 OSDArray allOsd = new OSDArray();
494
495 lock (m_knownMaterials)
496 {
497 foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials)
498 {
499 OSDMap matMap = new OSDMap();
500
501 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
502 matMap["Material"] = kvp.Value;
503 allOsd.Add(matMap);
504 matsCount++;
505 }
506 }
507
508 resp["Zipped"] = ZCompressOSD(allOsd, false);
509 m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
510
511 return OSDParser.SerializeLLSDXmlString(resp);
512 }
513
514 static string ZippedOsdBytesToString(byte[] bytes)
515 {
516 try
517 {
518 return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
519 }
520 catch (Exception e)
521 {
522 return "ZippedOsdBytesToString caught an exception: " + e.ToString();
523 }
524 }
525
526 /// <summary>
527 /// computes a UUID by hashing a OSD object
528 /// </summary>
529 /// <param name="osd"></param>
530 /// <returns></returns>
531 private static UUID HashOsd(OSD osd)
532 {
533 using (var md5 = MD5.Create())
534 using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false)))
535 return new UUID(md5.ComputeHash(ms), 0);
536 }
537
538 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
539 {
540 OSD osd = null;
541
542 using (MemoryStream msSinkCompressed = new MemoryStream())
543 {
544 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
545 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
546 {
547 CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut);
548 zOut.Close();
549 }
550
551 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
552 osd = OSD.FromBinary( msSinkCompressed.ToArray());
553 }
554
555 return osd;
556 }
557
558
559 public static OSD ZDecompressBytesToOsd(byte[] input)
560 {
561 OSD osd = null;
562
563 using (MemoryStream msSinkUnCompressed = new MemoryStream())
564 {
565 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
566 {
567 CopyStream(new MemoryStream(input), zOut);
568 zOut.Close();
569 }
570 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
571 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
572 }
573
574 return osd;
575 }
576
577 static void CopyStream(System.IO.Stream input, System.IO.Stream output)
578 {
579 byte[] buffer = new byte[2048];
580 int len;
581 while ((len = input.Read(buffer, 0, 2048)) > 0)
582 {
583 output.Write(buffer, 0, len);
584 }
585
586 output.Flush();
587 }
588
589 // FIXME: This code is currently still in UuidGatherer since we cannot use Scene.EventManager as some
590 // calls to the gatherer are done for objects with no scene.
591// /// <summary>
592// /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
593// /// </summary>
594// /// <param name="part"></param>
595// /// <param name="assetUuids"></param>
596// private void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
597// {
598// // scan thru the dynAttrs map of this part for any textures used as materials
599// OSD osdMaterials = null;
600//
601// lock (part.DynAttrs)
602// {
603// if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
604// {
605// OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
606// if (materialsStore == null)
607// return;
608//
609// materialsStore.TryGetValue("Materials", out osdMaterials);
610// }
611//
612// if (osdMaterials != null)
613// {
614// //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
615//
616// if (osdMaterials is OSDArray)
617// {
618// OSDArray matsArr = osdMaterials as OSDArray;
619// foreach (OSDMap matMap in matsArr)
620// {
621// try
622// {
623// if (matMap.ContainsKey("Material"))
624// {
625// OSDMap mat = matMap["Material"] as OSDMap;
626// if (mat.ContainsKey("NormMap"))
627// {
628// UUID normalMapId = mat["NormMap"].AsUUID();
629// if (normalMapId != UUID.Zero)
630// {
631// assetUuids[normalMapId] = AssetType.Texture;
632// //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
633// }
634// }
635// if (mat.ContainsKey("SpecMap"))
636// {
637// UUID specularMapId = mat["SpecMap"].AsUUID();
638// if (specularMapId != UUID.Zero)
639// {
640// assetUuids[specularMapId] = AssetType.Texture;
641// //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
642// }
643// }
644// }
645//
646// }
647// catch (Exception e)
648// {
649// m_log.Warn("[MaterialsDemoModule]: exception getting materials: " + e.Message);
650// }
651// }
652// }
653// }
654// }
655// }
656 }
657} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
new file mode 100644
index 0000000..afb788b
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -0,0 +1,590 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Security.Cryptography; // for computing md5 hash
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
46
47using Ionic.Zlib;
48
49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
51// the available DLLs
52//[assembly: Addin("MaterialsModule", "1.0")]
53//[assembly: AddinDependency("OpenSim", "0.5")]
54
55namespace OpenSim.Region.OptionalModules.Materials
56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
58 public class MaterialsModule : INonSharedRegionModule
59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 public string Name { get { return "MaterialsModule"; } }
63
64 public Type ReplaceableInterface { get { return null; } }
65
66 private Scene m_scene = null;
67 private bool m_enabled = false;
68
69 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
70
71 public void Initialise(IConfigSource source)
72 {
73 IConfig config = source.Configs["Materials"];
74 if (config == null)
75 return;
76
77 m_enabled = config.GetBoolean("enable_materials", true);
78 if (!m_enabled)
79 return;
80
81 m_log.DebugFormat("[Materials]: Initialized");
82 }
83
84 public void Close()
85 {
86 if (!m_enabled)
87 return;
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (!m_enabled)
93 return;
94
95 m_scene = scene;
96 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
97 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
98 }
99
100 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
101 {
102 foreach (var part in obj.Parts)
103 if (part != null)
104 GetStoredMaterialsInPart(part);
105 }
106
107 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
108 {
109 string capsBase = "/CAPS/" + caps.CapsObjectPath;
110
111 IRequestHandler renderMaterialsPostHandler
112 = new RestStreamHandler("POST", capsBase + "/",
113 (request, path, param, httpRequest, httpResponse)
114 => RenderMaterialsPostCap(request, agentID),
115 "RenderMaterials", null);
116 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
117
118 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
119 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
120 // handler normally and then add a GET handler via MainServer
121
122 IRequestHandler renderMaterialsGetHandler
123 = new RestStreamHandler("GET", capsBase + "/",
124 (request, path, param, httpRequest, httpResponse)
125 => RenderMaterialsGetCap(request),
126 "RenderMaterials", null);
127 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
128
129 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
130 IRequestHandler renderMaterialsPutHandler
131 = new RestStreamHandler("PUT", capsBase + "/",
132 (request, path, param, httpRequest, httpResponse)
133 => RenderMaterialsPostCap(request, agentID),
134 "RenderMaterials", null);
135 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
136 }
137
138 public void RemoveRegion(Scene scene)
139 {
140 if (!m_enabled)
141 return;
142
143 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
144 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
145 }
146
147 public void RegionLoaded(Scene scene)
148 {
149 }
150
151 /// <summary>
152 /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
153 /// </summary>
154 /// <param name="part"></param>
155 private void GetLegacyStoredMaterialsInPart(SceneObjectPart part)
156 {
157 if (part.DynAttrs == null)
158 return;
159
160 OSD OSMaterials = null;
161 OSDArray matsArr = null;
162
163 lock (part.DynAttrs)
164 {
165 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
166 {
167 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
168
169 if (materialsStore == null)
170 return;
171
172 materialsStore.TryGetValue("Materials", out OSMaterials);
173 }
174
175 if (OSMaterials != null && OSMaterials is OSDArray)
176 matsArr = OSMaterials as OSDArray;
177 else
178 return;
179 }
180
181 if (matsArr == null)
182 return;
183
184 foreach (OSD elemOsd in matsArr)
185 {
186 if (elemOsd != null && elemOsd is OSDMap)
187 {
188 OSDMap matMap = elemOsd as OSDMap;
189 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
190 {
191 try
192 {
193 lock (m_regionMaterials)
194 m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
195 }
196 catch (Exception e)
197 {
198 m_log.Warn("[Materials]: exception decoding persisted legacy material: " + e.ToString());
199 }
200 }
201 }
202 }
203 }
204
205 /// <summary>
206 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
207 /// </summary>
208 private void GetStoredMaterialsInPart(SceneObjectPart part)
209 {
210 if (part.Shape == null)
211 return;
212
213 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
214 if (te == null)
215 return;
216
217 GetLegacyStoredMaterialsInPart(part);
218
219 GetStoredMaterialInFace(part, te.DefaultTexture);
220
221 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
222 {
223 if (face != null)
224 GetStoredMaterialInFace(part, face);
225 }
226 }
227
228 /// <summary>
229 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
230 /// </summary>
231 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
232 {
233 UUID id = face.MaterialID;
234 if (id == UUID.Zero)
235 return;
236
237 lock (m_regionMaterials)
238 {
239 if (m_regionMaterials.ContainsKey(id))
240 return;
241
242 byte[] data = m_scene.AssetService.GetData(id.ToString());
243 if (data == null)
244 {
245 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
246 return;
247 }
248
249 OSDMap mat;
250 try
251 {
252 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
253 }
254 catch (Exception e)
255 {
256 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
257 return;
258 }
259
260 m_regionMaterials[id] = mat;
261 }
262 }
263
264 public string RenderMaterialsPostCap(string request, UUID agentID)
265 {
266 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
267 OSDMap resp = new OSDMap();
268
269 OSDMap materialsFromViewer = null;
270
271 OSDArray respArr = new OSDArray();
272
273 if (req.ContainsKey("Zipped"))
274 {
275 OSD osd = null;
276
277 byte[] inBytes = req["Zipped"].AsBinary();
278
279 try
280 {
281 osd = ZDecompressBytesToOsd(inBytes);
282
283 if (osd != null)
284 {
285 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
286 {
287 foreach (OSD elem in (OSDArray)osd)
288 {
289 try
290 {
291 UUID id = new UUID(elem.AsBinary(), 0);
292
293 lock (m_regionMaterials)
294 {
295 if (m_regionMaterials.ContainsKey(id))
296 {
297 OSDMap matMap = new OSDMap();
298 matMap["ID"] = OSD.FromBinary(id.GetBytes());
299 matMap["Material"] = m_regionMaterials[id];
300 respArr.Add(matMap);
301 }
302 else
303 {
304 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
305
306 // Theoretically we could try to load the material from the assets service,
307 // but that shouldn't be necessary because the viewer should only request
308 // materials that exist in a prim on the region, and all of these materials
309 // are already stored in m_regionMaterials.
310 }
311 }
312 }
313 catch (Exception e)
314 {
315 m_log.Error("Error getting materials in response to viewer request", e);
316 continue;
317 }
318 }
319 }
320 else if (osd is OSDMap) // request to assign a material
321 {
322 materialsFromViewer = osd as OSDMap;
323
324 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
325 {
326 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
327 if (matsOsd is OSDArray)
328 {
329 OSDArray matsArr = matsOsd as OSDArray;
330
331 try
332 {
333 foreach (OSDMap matsMap in matsArr)
334 {
335 uint primLocalID = 0;
336 try {
337 primLocalID = matsMap["ID"].AsUInteger();
338 }
339 catch (Exception e) {
340 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
341 continue;
342 }
343
344 OSDMap mat = null;
345 try
346 {
347 mat = matsMap["Material"] as OSDMap;
348 }
349 catch (Exception e)
350 {
351 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
352 continue;
353 }
354
355 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
356 if (sop == null)
357 {
358 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
359 continue;
360 }
361
362 if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
363 {
364 m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID);
365 continue;
366 }
367
368 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
369 if (te == null)
370 {
371 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
372 continue;
373 }
374
375
376 UUID id;
377 if (mat == null)
378 {
379 // This happens then the user removes a material from a prim
380 id = UUID.Zero;
381 }
382 else
383 {
384 id = StoreMaterialAsAsset(agentID, mat, sop);
385 }
386
387
388 int face = -1;
389
390 if (matsMap.ContainsKey("Face"))
391 {
392 face = matsMap["Face"].AsInteger();
393 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
394 faceEntry.MaterialID = id;
395 }
396 else
397 {
398 if (te.DefaultTexture == null)
399 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
400 else
401 te.DefaultTexture.MaterialID = id;
402 }
403
404 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
405
406 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
407 sop.Shape.TextureEntry = te.GetBytes();
408
409 if (sop.ParentGroup != null)
410 {
411 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
412 sop.UpdateFlag = UpdateRequired.FULL;
413 sop.ParentGroup.HasGroupChanged = true;
414 sop.ScheduleFullUpdate();
415 }
416 }
417 }
418 catch (Exception e)
419 {
420 m_log.Warn("[Materials]: exception processing received material ", e);
421 }
422 }
423 }
424 }
425 }
426
427 }
428 catch (Exception e)
429 {
430 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
431 //return "";
432 }
433 }
434
435
436 resp["Zipped"] = ZCompressOSD(respArr, false);
437 string response = OSDParser.SerializeLLSDXmlString(resp);
438
439 //m_log.Debug("[Materials]: cap request: " + request);
440 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
441 //m_log.Debug("[Materials]: cap response: " + response);
442 return response;
443 }
444
445 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
446 {
447 UUID id;
448 // Material UUID = hash of the material's data.
449 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
450 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
451 using (var md5 = MD5.Create())
452 id = new UUID(md5.ComputeHash(data), 0);
453
454 lock (m_regionMaterials)
455 {
456 if (!m_regionMaterials.ContainsKey(id))
457 {
458 m_regionMaterials[id] = mat;
459
460 // This asset might exist already, but it's ok to try to store it again
461 string name = "Material " + ChooseMaterialName(mat, sop);
462 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
463 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
464 asset.Data = data;
465 m_scene.AssetService.Store(asset);
466 }
467 }
468 return id;
469 }
470
471 /// <summary>
472 /// Use heuristics to choose a good name for the material.
473 /// </summary>
474 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
475 {
476 UUID normMap = mat["NormMap"].AsUUID();
477 if (normMap != UUID.Zero)
478 {
479 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
480 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
481 return asset.Name;
482 }
483
484 UUID specMap = mat["SpecMap"].AsUUID();
485 if (specMap != UUID.Zero)
486 {
487 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
488 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
489 return asset.Name;
490 }
491
492 if (sop.Name != "Primitive")
493 return sop.Name;
494
495 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
496 return sop.ParentGroup.Name;
497
498 return "";
499 }
500
501
502 public string RenderMaterialsGetCap(string request)
503 {
504 OSDMap resp = new OSDMap();
505 int matsCount = 0;
506 OSDArray allOsd = new OSDArray();
507
508 lock (m_regionMaterials)
509 {
510 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
511 {
512 OSDMap matMap = new OSDMap();
513
514 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
515 matMap["Material"] = kvp.Value;
516 allOsd.Add(matMap);
517 matsCount++;
518 }
519 }
520
521 resp["Zipped"] = ZCompressOSD(allOsd, false);
522
523 return OSDParser.SerializeLLSDXmlString(resp);
524 }
525
526 private static string ZippedOsdBytesToString(byte[] bytes)
527 {
528 try
529 {
530 return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
531 }
532 catch (Exception e)
533 {
534 return "ZippedOsdBytesToString caught an exception: " + e.ToString();
535 }
536 }
537
538 /// <summary>
539 /// computes a UUID by hashing a OSD object
540 /// </summary>
541 /// <param name="osd"></param>
542 /// <returns></returns>
543 private static UUID HashOsd(OSD osd)
544 {
545 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
546 using (var md5 = MD5.Create())
547 return new UUID(md5.ComputeHash(data), 0);
548 }
549
550 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
551 {
552 OSD osd = null;
553
554 byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
555
556 using (MemoryStream msSinkCompressed = new MemoryStream())
557 {
558 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
559 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
560 {
561 zOut.Write(data, 0, data.Length);
562 }
563
564 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
565 osd = OSD.FromBinary(msSinkCompressed.ToArray());
566 }
567
568 return osd;
569 }
570
571
572 public static OSD ZDecompressBytesToOsd(byte[] input)
573 {
574 OSD osd = null;
575
576 using (MemoryStream msSinkUnCompressed = new MemoryStream())
577 {
578 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
579 {
580 zOut.Write(input, 0, input.Length);
581 }
582
583 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
584 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
585 }
586
587 return osd;
588 }
589 }
590}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
new file mode 100644
index 0000000..d4b19dd
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
@@ -0,0 +1,195 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreCommandsModule")]
48
49 public class JsonStoreCommandsModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56
57 private Scene m_scene = null;
58 //private IJsonStoreModule m_store;
59 private JsonStoreModule m_store;
60
61#region Region Module interface
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 // m_log.InfoFormat("[JsonStore] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.Error("[JsonStore]: initialization error: {0}", e);
96 return;
97 }
98
99 if (m_enabled)
100 m_log.DebugFormat("[JsonStore]: module is enabled");
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 if (m_enabled)
128 {
129 m_scene = scene;
130
131 }
132 }
133
134 // -----------------------------------------------------------------
135 /// <summary>
136 /// </summary>
137 // -----------------------------------------------------------------
138 public void RemoveRegion(Scene scene)
139 {
140 // need to remove all references to the scene in the subscription
141 // list to enable full garbage collection of the scene object
142 }
143
144 // -----------------------------------------------------------------
145 /// <summary>
146 /// Called when all modules have been added for a region. This is
147 /// where we hook up events
148 /// </summary>
149 // -----------------------------------------------------------------
150 public void RegionLoaded(Scene scene)
151 {
152 if (m_enabled)
153 {
154 m_scene = scene;
155
156 m_store = (JsonStoreModule) m_scene.RequestModuleInterface<IJsonStoreModule>();
157 if (m_store == null)
158 {
159 m_log.ErrorFormat("[JsonStoreCommands]: JsonModule interface not defined");
160 m_enabled = false;
161 return;
162 }
163
164 scene.AddCommand("JsonStore", this, "jsonstore stats", "jsonstore stats",
165 "Display statistics about the state of the JsonStore module", "",
166 CmdStats);
167 }
168 }
169
170 /// -----------------------------------------------------------------
171 /// <summary>
172 /// </summary>
173 // -----------------------------------------------------------------
174 public Type ReplaceableInterface
175 {
176 get { return null; }
177 }
178
179#endregion
180
181#region Commands
182
183 private void CmdStats(string module, string[] cmd)
184 {
185 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
186 return;
187
188 JsonStoreStats stats = m_store.GetStoreStats();
189 MainConsole.Instance.OutputFormat("{0}\t{1}",m_scene.RegionInfo.RegionName,stats.StoreCount);
190 }
191
192#endregion
193
194 }
195}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index 5fbfcc5..b502a55 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic; 42using System.Collections.Generic;
43using System.Text.RegularExpressions; 43using System.Text.RegularExpressions;
44 44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore 45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{ 46{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
@@ -60,6 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
60 private Scene m_scene = null; 59 private Scene m_scene = null;
61 60
62 private Dictionary<UUID,JsonStore> m_JsonValueStore; 61 private Dictionary<UUID,JsonStore> m_JsonValueStore;
62
63 private UUID m_sharedStore; 63 private UUID m_sharedStore;
64 64
65#region Region Module interface 65#region Region Module interface
@@ -140,6 +140,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
140 m_sharedStore = UUID.Zero; 140 m_sharedStore = UUID.Zero;
141 m_JsonValueStore = new Dictionary<UUID,JsonStore>(); 141 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
142 m_JsonValueStore.Add(m_sharedStore,new JsonStore("")); 142 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
143
144 scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
143 } 145 }
144 } 146 }
145 147
@@ -149,6 +151,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
149 // ----------------------------------------------------------------- 151 // -----------------------------------------------------------------
150 public void RemoveRegion(Scene scene) 152 public void RemoveRegion(Scene scene)
151 { 153 {
154 scene.EventManager.OnObjectBeingRemovedFromScene -= EventManagerOnObjectBeingRemovedFromScene;
155
152 // need to remove all references to the scene in the subscription 156 // need to remove all references to the scene in the subscription
153 // list to enable full garbage collection of the scene object 157 // list to enable full garbage collection of the scene object
154 } 158 }
@@ -161,7 +165,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
161 // ----------------------------------------------------------------- 165 // -----------------------------------------------------------------
162 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
163 { 167 {
164 if (m_enabled) {} 168 if (m_enabled)
169 {
170 }
165 } 171 }
166 172
167 /// ----------------------------------------------------------------- 173 /// -----------------------------------------------------------------
@@ -175,8 +181,39 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 181
176#endregion 182#endregion
177 183
184#region SceneEvents
185 // -----------------------------------------------------------------
186 /// <summary>
187 ///
188 /// </summary>
189 // -----------------------------------------------------------------
190 public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
191 {
192 obj.ForEachPart(delegate(SceneObjectPart sop) { DestroyStore(sop.UUID); } );
193 }
194
195#endregion
196
178#region ScriptInvocationInteface 197#region ScriptInvocationInteface
179 198
199
200 // -----------------------------------------------------------------
201 /// <summary>
202 ///
203 /// </summary>
204 // -----------------------------------------------------------------
205 public JsonStoreStats GetStoreStats()
206 {
207 JsonStoreStats stats;
208
209 lock (m_JsonValueStore)
210 {
211 stats.StoreCount = m_JsonValueStore.Count;
212 }
213
214 return stats;
215 }
216
180 // ----------------------------------------------------------------- 217 // -----------------------------------------------------------------
181 /// <summary> 218 /// <summary>
182 /// 219 ///
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index 1bb5aee..9fbfb66 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -59,7 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
59 59
60 private IScriptModuleComms m_comms; 60 private IScriptModuleComms m_comms;
61 private IJsonStoreModule m_store; 61 private IJsonStoreModule m_store;
62 62
63 private Dictionary<UUID,HashSet<UUID>> m_scriptStores = new Dictionary<UUID,HashSet<UUID>>();
64
63#region Region Module interface 65#region Region Module interface
64 66
65 // ----------------------------------------------------------------- 67 // -----------------------------------------------------------------
@@ -126,6 +128,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
126 // ----------------------------------------------------------------- 128 // -----------------------------------------------------------------
127 public void AddRegion(Scene scene) 129 public void AddRegion(Scene scene)
128 { 130 {
131 scene.EventManager.OnScriptReset += HandleScriptReset;
132 scene.EventManager.OnRemoveScript += HandleScriptReset;
129 } 133 }
130 134
131 // ----------------------------------------------------------------- 135 // -----------------------------------------------------------------
@@ -134,12 +138,34 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
134 // ----------------------------------------------------------------- 138 // -----------------------------------------------------------------
135 public void RemoveRegion(Scene scene) 139 public void RemoveRegion(Scene scene)
136 { 140 {
141 scene.EventManager.OnScriptReset -= HandleScriptReset;
142 scene.EventManager.OnRemoveScript -= HandleScriptReset;
143
137 // need to remove all references to the scene in the subscription 144 // need to remove all references to the scene in the subscription
138 // list to enable full garbage collection of the scene object 145 // list to enable full garbage collection of the scene object
139 } 146 }
140 147
141 // ----------------------------------------------------------------- 148 // -----------------------------------------------------------------
142 /// <summary> 149 /// <summary>
150 /// </summary>
151 // -----------------------------------------------------------------
152 private void HandleScriptReset(uint localID, UUID itemID)
153 {
154 HashSet<UUID> stores;
155
156 lock (m_scriptStores)
157 {
158 if (! m_scriptStores.TryGetValue(itemID, out stores))
159 return;
160 m_scriptStores.Remove(itemID);
161 }
162
163 foreach (UUID id in stores)
164 m_store.DestroyStore(id);
165 }
166
167 // -----------------------------------------------------------------
168 /// <summary>
143 /// Called when all modules have been added for a region. This is 169 /// Called when all modules have been added for a region. This is
144 /// where we hook up events 170 /// where we hook up events
145 /// </summary> 171 /// </summary>
@@ -250,6 +276,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
250 if (! m_store.CreateStore(value, ref uuid)) 276 if (! m_store.CreateStore(value, ref uuid))
251 GenerateRuntimeError("Failed to create Json store"); 277 GenerateRuntimeError("Failed to create Json store");
252 278
279 lock (m_scriptStores)
280 {
281 if (! m_scriptStores.ContainsKey(scriptID))
282 m_scriptStores[scriptID] = new HashSet<UUID>();
283
284 m_scriptStores[scriptID].Add(uuid);
285 }
253 return uuid; 286 return uuid;
254 } 287 }
255 288
@@ -261,6 +294,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
261 [ScriptInvocation] 294 [ScriptInvocation]
262 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) 295 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
263 { 296 {
297 lock(m_scriptStores)
298 {
299 if (m_scriptStores.ContainsKey(scriptID))
300 m_scriptStores[scriptID].Remove(storeID);
301 }
302
264 return m_store.DestroyStore(storeID) ? 1 : 0; 303 return m_store.DestroyStore(storeID) ? 1 : 0;
265 } 304 }
266 305