aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs9
-rw-r--r--OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs6
-rw-r--r--OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs3
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs269
-rw-r--r--OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs174
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs129
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs421
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs109
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs23
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs111
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs449
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs1343
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs440
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs625
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs42
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs19
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs69
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs218
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs197
-rw-r--r--OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs256
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs76
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs403
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs66
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs9
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs198
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs21
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs226
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs46
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs49
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs20
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs66
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs26
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs79
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs73
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-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.cs33
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs218
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs256
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs298
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs32
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs448
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs131
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs538
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs44
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs185
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs147
85 files changed, 7192 insertions, 1837 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..1e14f45 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33 33
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Region.Framework.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.Agent.AssetTransaction 38namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
@@ -119,6 +120,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
119 } 120 }
120 else 121 else
121 { 122 {
123 // Check if the xfer is a terrain xfer
124 IEstateModule estateModule = m_Scene.RequestModuleInterface<IEstateModule>();
125 if (estateModule != null)
126 {
127 if (estateModule.IsTerrainXfer(xferID))
128 return;
129 }
130
122 m_log.ErrorFormat( 131 m_log.ErrorFormat(
123 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", 132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
124 xferID, packetID, data.Length); 133 xferID, packetID, data.Length);
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index 3764685..d9b0eff 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
166 166
167 // Do Decode! 167 // Do Decode!
168 if (decode) 168 if (decode)
169 Decode(assetID, j2kData); 169 Util.FireAndForget(delegate { Decode(assetID, j2kData); });
170 } 170 }
171 } 171 }
172 172
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index f43305f..9b0e1f4 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -194,10 +194,12 @@ namespace OpenSim.Region.CoreModules.Asset
194 194
195 #region IImprovedAssetCache Members 195 #region IImprovedAssetCache Members
196 196
197
198 public bool Check(string id) 197 public bool Check(string id)
199 { 198 {
200 return false; 199 AssetBase asset;
200
201 // XXX:This is probably not an efficient implementation.
202 return m_cache.TryGetValue(id, out asset);
201 } 203 }
202 204
203 /// <summary> 205 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index 58ce61a..f720748 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -114,7 +114,8 @@ namespace OpenSim.Region.CoreModules.Asset
114 // 114 //
115 public bool Check(string id) 115 public bool Check(string id)
116 { 116 {
117 return false; 117 // XXX This is probably not an efficient implementation.
118 return Get(id) != null;
118 } 119 }
119 120
120 public void Cache(AssetBase asset) 121 public void Cache(AssetBase asset)
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index d510d82..5468cdc 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -31,17 +31,16 @@
31using System; 31using System;
32using System.IO; 32using System.IO;
33using System.Collections.Generic; 33using System.Collections.Generic;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Runtime.Serialization; 36using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary; 37using System.Runtime.Serialization.Formatters.Binary;
37using System.Threading; 38using System.Threading;
38using System.Timers; 39using System.Timers;
39
40using log4net; 40using log4net;
41using Nini.Config; 41using Nini.Config;
42using Mono.Addins; 42using Mono.Addins;
43using OpenMetaverse; 43using OpenMetaverse;
44
45using OpenSim.Framework; 44using OpenSim.Framework;
46using OpenSim.Framework.Console; 45using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
@@ -76,8 +75,6 @@ namespace OpenSim.Region.CoreModules.Asset
76 private static ulong m_RequestsForInprogress; 75 private static ulong m_RequestsForInprogress;
77 private static ulong m_DiskHits; 76 private static ulong m_DiskHits;
78 private static ulong m_MemoryHits; 77 private static ulong m_MemoryHits;
79 private static double m_HitRateMemory;
80 private static double m_HitRateFile;
81 78
82#if WAIT_ON_INPROGRESS_REQUESTS 79#if WAIT_ON_INPROGRESS_REQUESTS
83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 80 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
@@ -251,71 +248,68 @@ namespace OpenSim.Region.CoreModules.Asset
251 248
252 private void UpdateFileCache(string key, AssetBase asset) 249 private void UpdateFileCache(string key, AssetBase asset)
253 { 250 {
254 // TODO: Spawn this off to some seperate thread to do the actual writing 251 string filename = GetFileName(key);
255 if (asset != null)
256 {
257 string filename = GetFileName(key);
258 252
259 try 253 try
254 {
255 // If the file is already cached, don't cache it, just touch it so access time is updated
256 if (File.Exists(filename))
260 { 257 {
261 // If the file is already cached, don't cache it, just touch it so access time is updated 258 // We don't really want to know about sharing
262 if (File.Exists(filename)) 259 // violations here. If the file is locked, then
260 // the other thread has updated the time for us.
261 try
263 { 262 {
264 // We don't really want to know about sharing 263 lock (m_CurrentlyWriting)
265 // violations here. If the file is locked, then
266 // the other thread has updated the time for us.
267 try
268 { 264 {
269 lock (m_CurrentlyWriting) 265 if (!m_CurrentlyWriting.Contains(filename))
270 { 266 File.SetLastAccessTime(filename, DateTime.Now);
271 if (!m_CurrentlyWriting.Contains(filename))
272 File.SetLastAccessTime(filename, DateTime.Now);
273 }
274 } 267 }
275 catch 268 }
269 catch
270 {
271 }
272 }
273 else
274 {
275 // Once we start writing, make sure we flag that we're writing
276 // that object to the cache so that we don't try to write the
277 // same file multiple times.
278 lock (m_CurrentlyWriting)
279 {
280#if WAIT_ON_INPROGRESS_REQUESTS
281 if (m_CurrentlyWriting.ContainsKey(filename))
276 { 282 {
283 return;
277 } 284 }
278 } else { 285 else
279
280 // Once we start writing, make sure we flag that we're writing
281 // that object to the cache so that we don't try to write the
282 // same file multiple times.
283 lock (m_CurrentlyWriting)
284 { 286 {
285#if WAIT_ON_INPROGRESS_REQUESTS 287 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
286 if (m_CurrentlyWriting.ContainsKey(filename)) 288 }
287 {
288 return;
289 }
290 else
291 {
292 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
293 }
294 289
295#else 290#else
296 if (m_CurrentlyWriting.Contains(filename)) 291 if (m_CurrentlyWriting.Contains(filename))
297 { 292 {
298 return; 293 return;
299 }
300 else
301 {
302 m_CurrentlyWriting.Add(filename);
303 }
304#endif
305
306 } 294 }
295 else
296 {
297 m_CurrentlyWriting.Add(filename);
298 }
299#endif
307 300
308 Util.FireAndForget(
309 delegate { WriteFileCache(filename, asset); });
310 } 301 }
311 } 302
312 catch (Exception e) 303 Util.FireAndForget(
313 { 304 delegate { WriteFileCache(filename, asset); });
314 m_log.ErrorFormat(
315 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
316 asset.ID, e.Message, e.StackTrace);
317 } 305 }
318 } 306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat(
310 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
311 asset.ID, e.Message, e.StackTrace);
312 }
319 } 313 }
320 314
321 public void Cache(AssetBase asset) 315 public void Cache(AssetBase asset)
@@ -350,15 +344,9 @@ namespace OpenSim.Region.CoreModules.Asset
350 344
351 private bool CheckFromMemoryCache(string id) 345 private bool CheckFromMemoryCache(string id)
352 { 346 {
353 AssetBase asset = null; 347 return m_MemoryCache.Contains(id);
354
355 if (m_MemoryCache.TryGetValue(id, out asset))
356 return true;
357
358 return false;
359 } 348 }
360 349
361
362 /// <summary> 350 /// <summary>
363 /// Try to get an asset from the file cache. 351 /// Try to get an asset from the file cache.
364 /// </summary> 352 /// </summary>
@@ -396,15 +384,16 @@ namespace OpenSim.Region.CoreModules.Asset
396 384
397 if (File.Exists(filename)) 385 if (File.Exists(filename))
398 { 386 {
399 FileStream stream = null;
400 try 387 try
401 { 388 {
402 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 389 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
403 BinaryFormatter bformatter = new BinaryFormatter(); 390 {
391 BinaryFormatter bformatter = new BinaryFormatter();
404 392
405 asset = (AssetBase)bformatter.Deserialize(stream); 393 asset = (AssetBase)bformatter.Deserialize(stream);
406 394
407 m_DiskHits++; 395 m_DiskHits++;
396 }
408 } 397 }
409 catch (System.Runtime.Serialization.SerializationException e) 398 catch (System.Runtime.Serialization.SerializationException e)
410 { 399 {
@@ -423,12 +412,6 @@ namespace OpenSim.Region.CoreModules.Asset
423 m_log.WarnFormat( 412 m_log.WarnFormat(
424 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 413 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
425 filename, id, e.Message, e.StackTrace); 414 filename, id, e.Message, e.StackTrace);
426
427 }
428 finally
429 {
430 if (stream != null)
431 stream.Close();
432 } 415 }
433 } 416 }
434 417
@@ -440,36 +423,19 @@ namespace OpenSim.Region.CoreModules.Asset
440 bool found = false; 423 bool found = false;
441 424
442 string filename = GetFileName(id); 425 string filename = GetFileName(id);
426
443 if (File.Exists(filename)) 427 if (File.Exists(filename))
444 { 428 {
445 // actually check if we can open it, and so update expire
446 FileStream stream = null;
447 try 429 try
448 { 430 {
449 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 431 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
450 if (stream != null)
451 { 432 {
452 found = true; 433 if (stream != null)
453 stream.Close(); 434 found = true;
454 } 435 }
455
456 }
457 catch (System.Runtime.Serialization.SerializationException e)
458 {
459 found = false;
460 m_log.ErrorFormat(
461 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
462 filename, id, e.Message, e.StackTrace);
463
464 // If there was a problem deserializing the asset, the asset may
465 // either be corrupted OR was serialized under an old format
466 // {different version of AssetBase} -- we should attempt to
467 // delete it and re-cache
468 File.Delete(filename);
469 } 436 }
470 catch (Exception e) 437 catch (Exception e)
471 { 438 {
472 found = false;
473 m_log.ErrorFormat( 439 m_log.ErrorFormat(
474 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", 440 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
475 filename, id, e.Message, e.StackTrace); 441 filename, id, e.Message, e.StackTrace);
@@ -498,18 +464,9 @@ namespace OpenSim.Region.CoreModules.Asset
498 464
499 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 465 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
500 { 466 {
501 m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0;
502
503 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); 467 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit");
504 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests);
505 468
506 if (m_MemoryCacheEnabled) 469 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
507 {
508 m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0;
509 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests);
510 }
511
512 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress);
513 } 470 }
514 471
515 return asset; 472 return asset;
@@ -530,11 +487,6 @@ namespace OpenSim.Region.CoreModules.Asset
530 return Get(id); 487 return Get(id);
531 } 488 }
532 489
533 public AssetBase CheckCached(string id)
534 {
535 return Get(id);
536 }
537
538 public void Expire(string id) 490 public void Expire(string id)
539 { 491 {
540 if (m_LogLevel >= 2) 492 if (m_LogLevel >= 2)
@@ -636,6 +588,11 @@ namespace OpenSim.Region.CoreModules.Asset
636 dir, dirSize); 588 dir, dirSize);
637 } 589 }
638 } 590 }
591 catch (DirectoryNotFoundException)
592 {
593 // If we get here, another node on the same box has
594 // already removed the directory. Continue with next.
595 }
639 catch (Exception e) 596 catch (Exception e)
640 { 597 {
641 m_log.Warn( 598 m_log.Warn(
@@ -819,7 +776,7 @@ namespace OpenSim.Region.CoreModules.Asset
819 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 776 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
820 777
821 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 778 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
822 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 779 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
823 780
824 foreach (Scene s in m_Scenes) 781 foreach (Scene s in m_Scenes)
825 { 782 {
@@ -842,7 +799,7 @@ namespace OpenSim.Region.CoreModules.Asset
842 else if (storeUncached) 799 else if (storeUncached)
843 { 800 {
844 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 801 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
845 if (cachedAsset == null && assets[assetID] != AssetType.Unknown) 802 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
846 m_log.DebugFormat( 803 m_log.DebugFormat(
847 "[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", 804 "[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",
848 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); 805 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
@@ -891,45 +848,77 @@ namespace OpenSim.Region.CoreModules.Asset
891 } 848 }
892 } 849 }
893 850
851 private List<string> GenerateCacheHitReport()
852 {
853 List<string> outputLines = new List<string>();
854
855 double fileHitRate = (double)m_DiskHits / m_Requests * 100.0;
856 outputLines.Add(
857 string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
858
859 if (m_MemoryCacheEnabled)
860 {
861 double memHitRate = (double)m_MemoryHits / m_Requests * 100.0;
862
863 outputLines.Add(
864 string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests));
865 }
866
867 outputLines.Add(
868 string.Format(
869 "Unnecessary requests due to requests for assets that are currently downloading: {0}",
870 m_RequestsForInprogress));
871
872 return outputLines;
873 }
874
894 #region Console Commands 875 #region Console Commands
895 private void HandleConsoleCommand(string module, string[] cmdparams) 876 private void HandleConsoleCommand(string module, string[] cmdparams)
896 { 877 {
878 ICommandConsole con = MainConsole.Instance;
879
897 if (cmdparams.Length >= 2) 880 if (cmdparams.Length >= 2)
898 { 881 {
899 string cmd = cmdparams[1]; 882 string cmd = cmdparams[1];
883
900 switch (cmd) 884 switch (cmd)
901 { 885 {
902 case "status": 886 case "status":
903 if (m_MemoryCacheEnabled) 887 if (m_MemoryCacheEnabled)
904 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count); 888 con.OutputFormat("Memory Cache: {0} assets", m_MemoryCache.Count);
905 else 889 else
906 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled"); 890 con.OutputFormat("Memory cache disabled");
907 891
908 if (m_FileCacheEnabled) 892 if (m_FileCacheEnabled)
909 { 893 {
910 int fileCount = GetFileCacheCount(m_CacheDirectory); 894 int fileCount = GetFileCacheCount(m_CacheDirectory);
911 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount); 895 con.OutputFormat("File Cache: {0} assets", fileCount);
896 }
897 else
898 {
899 con.Output("File cache disabled");
900 }
901
902 GenerateCacheHitReport().ForEach(l => con.Output(l));
903
904 if (m_FileCacheEnabled)
905 {
906 con.Output("Deep scans have previously been performed on the following regions:");
912 907
913 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 908 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
914 { 909 {
915 m_log.Info("[FLOTSAM ASSET CACHE]: Deep scans have previously been performed on the following regions:");
916
917 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 910 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
918 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 911 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
919 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 912 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
920 } 913 }
921 } 914 }
922 else
923 {
924 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
925 }
926 915
927 break; 916 break;
928 917
929 case "clear": 918 case "clear":
930 if (cmdparams.Length < 2) 919 if (cmdparams.Length < 2)
931 { 920 {
932 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]"); 921 con.Output("Usage is fcache clear [file] [memory]");
933 break; 922 break;
934 } 923 }
935 924
@@ -953,11 +942,11 @@ namespace OpenSim.Region.CoreModules.Asset
953 if (m_MemoryCacheEnabled) 942 if (m_MemoryCacheEnabled)
954 { 943 {
955 m_MemoryCache.Clear(); 944 m_MemoryCache.Clear();
956 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared."); 945 con.Output("Memory cache cleared.");
957 } 946 }
958 else 947 else
959 { 948 {
960 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled."); 949 con.Output("Memory cache not enabled.");
961 } 950 }
962 } 951 }
963 952
@@ -966,24 +955,22 @@ namespace OpenSim.Region.CoreModules.Asset
966 if (m_FileCacheEnabled) 955 if (m_FileCacheEnabled)
967 { 956 {
968 ClearFileCache(); 957 ClearFileCache();
969 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared."); 958 con.Output("File cache cleared.");
970 } 959 }
971 else 960 else
972 { 961 {
973 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled."); 962 con.Output("File cache not enabled.");
974 } 963 }
975 } 964 }
976 965
977 break; 966 break;
978 967
979 case "assets": 968 case "assets":
980 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 969 con.Output("Ensuring assets are cached for all scenes.");
981 970
982 Util.FireAndForget(delegate { 971 Util.FireAndForget(delegate {
983 int assetReferenceTotal = TouchAllSceneAssets(true); 972 int assetReferenceTotal = TouchAllSceneAssets(true);
984 m_log.InfoFormat( 973 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
985 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
986 assetReferenceTotal);
987 }); 974 });
988 975
989 break; 976 break;
@@ -991,7 +978,7 @@ namespace OpenSim.Region.CoreModules.Asset
991 case "expire": 978 case "expire":
992 if (cmdparams.Length < 3) 979 if (cmdparams.Length < 3)
993 { 980 {
994 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd); 981 con.OutputFormat("Invalid parameters for Expire, please specify a valid date & time", cmd);
995 break; 982 break;
996 } 983 }
997 984
@@ -1009,28 +996,27 @@ namespace OpenSim.Region.CoreModules.Asset
1009 996
1010 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 997 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
1011 { 998 {
1012 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd); 999 con.OutputFormat("{0} is not a valid date & time", cmd);
1013 break; 1000 break;
1014 } 1001 }
1015 1002
1016 if (m_FileCacheEnabled) 1003 if (m_FileCacheEnabled)
1017 CleanExpiredFiles(m_CacheDirectory, expirationDate); 1004 CleanExpiredFiles(m_CacheDirectory, expirationDate);
1018 else 1005 else
1019 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing."); 1006 con.OutputFormat("File cache not active, not clearing.");
1020 1007
1021 break; 1008 break;
1022 default: 1009 default:
1023 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd); 1010 con.OutputFormat("Unknown command {0}", cmd);
1024 break; 1011 break;
1025 } 1012 }
1026 } 1013 }
1027 else if (cmdparams.Length == 1) 1014 else if (cmdparams.Length == 1)
1028 { 1015 {
1029 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status"); 1016 con.Output("fcache assets - Attempt a deep cache of all assets in all scenes");
1030 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory"); 1017 con.Output("fcache expire <datetime> - Purge assets older then the specified date & time");
1031 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk"); 1018 con.Output("fcache clear [file] [memory] - Remove cached assets");
1032 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes"); 1019 con.Output("fcache status - Display cache status");
1033 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
1034 } 1020 }
1035 } 1021 }
1036 1022
@@ -1050,11 +1036,6 @@ namespace OpenSim.Region.CoreModules.Asset
1050 return asset.Data; 1036 return asset.Data;
1051 } 1037 }
1052 1038
1053 public bool CheckData(string id)
1054 {
1055 return Check(id); ;
1056 }
1057
1058 public bool Get(string id, object sender, AssetRetrieved handler) 1039 public bool Get(string id, object sender, AssetRetrieved handler)
1059 { 1040 {
1060 AssetBase asset = Get(id); 1041 AssetBase asset = Get(id);
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index ce9b546..5f76ac2 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Asset
117 117
118 public bool Check(string id) 118 public bool Check(string id)
119 { 119 {
120 return false; 120 return m_Cache.Contains(id);
121 } 121 }
122 122
123 public void Cache(AssetBase asset) 123 public void Cache(AssetBase asset)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 6495f3f..2c7cd40 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.IO; 31using System.IO;
32using System.Threading;
32using System.Xml; 33using System.Xml;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
@@ -51,6 +52,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 53
53 public int DebugLevel { get; set; } 54 public int DebugLevel { get; set; }
55
56 /// <summary>
57 /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes
58 /// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously.
59 /// </summary>
60 /// <remarks>
61 /// A value of 0 will apply no pause. The pause is specified in milliseconds.
62 /// </remarks>
63 public int ThrottlePer100PrimsRezzed { get; set; }
54 64
55 private Scene m_scene; 65 private Scene m_scene;
56 private IInventoryAccessModule m_invAccessModule; 66 private IInventoryAccessModule m_invAccessModule;
@@ -67,18 +77,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
67 { 77 {
68 IConfig config = source.Configs["Attachments"]; 78 IConfig config = source.Configs["Attachments"];
69 if (config != null) 79 if (config != null)
80 {
70 Enabled = config.GetBoolean("Enabled", true); 81 Enabled = config.GetBoolean("Enabled", true);
82
83 ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0);
84 }
71 else 85 else
86 {
72 Enabled = true; 87 Enabled = true;
88 }
73 } 89 }
74 90
75 public void AddRegion(Scene scene) 91 public void AddRegion(Scene scene)
76 { 92 {
77 m_scene = scene; 93 m_scene = scene;
78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
79
80 if (Enabled) 94 if (Enabled)
81 { 95 {
96 // Only register module with scene if it is enabled. All callers check for a null attachments module.
97 // Ideally, there should be a null attachments module for when this core attachments module has been
98 // disabled. Registering only when enabled allows for other attachments module implementations.
99 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 100 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); 101 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); 102 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
@@ -86,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
86 MainConsole.Instance.Commands.AddCommand( 104 MainConsole.Instance.Commands.AddCommand(
87 "Debug", 105 "Debug",
88 false, 106 false,
89 "debug attachments", 107 "debug attachments log",
90 "debug attachments [0|1]", 108 "debug attachments log [0|1]",
91 "Turn on attachments debugging\n" 109 "Turn on attachments debug logging",
92 + " <= 0 - turns off debugging\n" 110 " <= 0 - turns off debug logging\n"
93 + " >= 1 - turns on attachment message logging\n", 111 + " >= 1 - turns on attachment message debug logging",
94 HandleDebugAttachments); 112 HandleDebugAttachmentsLog);
113
114 MainConsole.Instance.Commands.AddCommand(
115 "Debug",
116 false,
117 "debug attachments throttle",
118 "debug attachments throttle <ms>",
119 "Turn on attachments throttling.",
120 "This requires a millisecond value. " +
121 " == 0 - disable throttling.\n"
122 + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.",
123 HandleDebugAttachmentsThrottle);
124
125 MainConsole.Instance.Commands.AddCommand(
126 "Debug",
127 false,
128 "debug attachments status",
129 "debug attachments status",
130 "Show current attachments debug status",
131 HandleDebugAttachmentsStatus);
95 } 132 }
96 133
97 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 134 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
98 } 135 }
99 136
100 private void HandleDebugAttachments(string module, string[] args) 137 private void HandleDebugAttachmentsLog(string module, string[] args)
101 { 138 {
102 int debugLevel; 139 int debugLevel;
103 140
104 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) 141 if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel)))
105 { 142 {
106 MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); 143 MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]");
107 } 144 }
108 else 145 else
109 { 146 {
@@ -113,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
113 } 150 }
114 } 151 }
115 152
153 private void HandleDebugAttachmentsThrottle(string module, string[] args)
154 {
155 int ms;
156
157 if (args.Length == 4 && int.TryParse(args[3], out ms))
158 {
159 ThrottlePer100PrimsRezzed = ms;
160 MainConsole.Instance.OutputFormat(
161 "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name);
162
163 return;
164 }
165
166 MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>");
167 }
168
169 private void HandleDebugAttachmentsStatus(string module, string[] args)
170 {
171 MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name);
172 MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel);
173 MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed);
174 }
175
116 /// <summary> 176 /// <summary>
117 /// Listen for client triggered running state changes so that we can persist the script's object if necessary. 177 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
118 /// </summary> 178 /// </summary>
@@ -273,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
273 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 333 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
274 foreach (AvatarAttachment attach in attachments) 334 foreach (AvatarAttachment attach in attachments)
275 { 335 {
276 uint p = (uint)attach.AttachPoint; 336 uint attachmentPt = (uint)attach.AttachPoint;
277 337
278// m_log.DebugFormat( 338// m_log.DebugFormat(
279// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", 339// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}",
@@ -302,13 +362,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
302 // If we're an NPC then skip all the item checks and manipulations since we don't have an 362 // If we're an NPC then skip all the item checks and manipulations since we don't have an
303 // inventory right now. 363 // inventory right now.
304 RezSingleAttachmentFromInventoryInternal( 364 RezSingleAttachmentFromInventoryInternal(
305 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, d); 365 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
306 } 366 }
307 catch (Exception e) 367 catch (Exception e)
308 { 368 {
309 UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; 369 UUID agentId = (sp.ControllingClient == null) ? default(UUID) : sp.ControllingClient.AgentId;
310 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", 370 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
311 attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); 371 attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace);
312 } 372 }
313 } 373 }
314 } 374 }
@@ -328,23 +388,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
328 388
329 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); 389 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
330 390
331 foreach (SceneObjectGroup so in attachments) 391 if (sp.PresenceType != PresenceType.Npc)
332 {
333 // Scripts MUST be snapshotted before the object is
334 // removed from the scene because doing otherwise will
335 // clobber the run flag
336 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
337 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
338 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
339 }
340
341 lock (sp.AttachmentsSyncLock)
342 { 392 {
343 foreach (SceneObjectGroup so in attachments) 393 foreach (SceneObjectGroup so in attachments)
344 UpdateDetachedObject(sp, so, scriptStates[so]); 394 {
345 395 // Scripts MUST be snapshotted before the object is
346 sp.ClearAttachments(); 396 // removed from the scene because doing otherwise will
397 // clobber the run flag
398 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
399 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
400 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
401 }
402
403 lock (sp.AttachmentsSyncLock)
404 {
405 foreach (SceneObjectGroup so in attachments)
406 UpdateDetachedObject(sp, so, scriptStates[so]);
407 sp.ClearAttachments();
408 }
347 } 409 }
410 else
411 {
412 lock (sp.AttachmentsSyncLock)
413 {
414 foreach (SceneObjectGroup so in attachments)
415 UpdateDetachedObject(sp, so, String.Empty);
416 sp.ClearAttachments();
417 }
418 }
348 } 419 }
349 420
350 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 421 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
@@ -422,13 +493,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
422 attachPos = Vector3.Zero; 493 attachPos = Vector3.Zero;
423 } 494 }
424 495
425 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. 496 // if the attachment point is the same as previous, make sure we get the saved
497 // position info.
498 if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint)
499 {
500 attachPos = group.RootPart.AttachedPos;
501 }
502
503 // AttachmentPt 0 means the client chose to 'wear' the attachment.
426 if (attachmentPt == (uint)AttachmentPoint.Default) 504 if (attachmentPt == (uint)AttachmentPoint.Default)
427 { 505 {
428 // Check object for stored attachment point 506 // Check object for stored attachment point
429 attachmentPt = group.AttachmentPoint; 507 attachmentPt = group.AttachmentPoint;
430 } 508 }
431 509
510 // if we didn't find an attach point, look for where it was last attached
511 if (attachmentPt == 0)
512 {
513 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
514 attachPos = group.RootPart.AttachedPos;
515 group.HasGroupChanged = true;
516 }
517
432 // if we still didn't find a suitable attachment point....... 518 // if we still didn't find a suitable attachment point.......
433 if (attachmentPt == 0) 519 if (attachmentPt == 0)
434 { 520 {
@@ -610,6 +696,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
610 if (changed && m_scene.AvatarFactory != null) 696 if (changed && m_scene.AvatarFactory != null)
611 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 697 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
612 698
699 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
700
613 sp.RemoveAttachment(so); 701 sp.RemoveAttachment(so);
614 so.FromItemID = UUID.Zero; 702 so.FromItemID = UUID.Zero;
615 703
@@ -638,6 +726,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
638 } 726 }
639 727
640 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 728 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
729
730 // Attach (NULL) stops scripts. We don't want that. Resume them.
731 so.ResumeScripts();
641 } 732 }
642 733
643 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 734 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
@@ -841,7 +932,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
841 m_scene.ForEachClient( 932 m_scene.ForEachClient(
842 client => 933 client =>
843 { if (client.AgentId != so.AttachedAvatar) 934 { if (client.AgentId != so.AttachedAvatar)
844 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); 935 client.SendKillObject(new List<uint>() { so.LocalId });
845 }); 936 });
846 } 937 }
847 938
@@ -934,6 +1025,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
934 // Remove the object from the scene so no more updates 1025 // Remove the object from the scene so no more updates
935 // are sent. Doing this before the below changes will ensure 1026 // are sent. Doing this before the below changes will ensure
936 // updates can't cause "HUD artefacts" 1027 // updates can't cause "HUD artefacts"
1028
937 m_scene.DeleteSceneObject(so, false, false); 1029 m_scene.DeleteSceneObject(so, false, false);
938 1030
939 // Prepare sog for storage 1031 // Prepare sog for storage
@@ -982,8 +1074,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
982 1074
983 if (DebugLevel > 0) 1075 if (DebugLevel > 0)
984 m_log.DebugFormat( 1076 m_log.DebugFormat(
985 "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", 1077 "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}",
986 objatt.Name, sp.Name, attachmentPt, m_scene.Name); 1078 objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
987 1079
988 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 1080 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
989 objatt.HasGroupChanged = false; 1081 objatt.HasGroupChanged = false;
@@ -1020,7 +1112,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1020 } 1112 }
1021 1113
1022 if (tainted) 1114 if (tainted)
1023 objatt.HasGroupChanged = true; 1115 objatt.HasGroupChanged = true;
1116
1117 if (ThrottlePer100PrimsRezzed > 0)
1118 {
1119 int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
1120
1121 if (DebugLevel > 0)
1122 m_log.DebugFormat(
1123 "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
1124 throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
1125
1126 Thread.Sleep(throttleMs);
1127 }
1024 1128
1025 return objatt; 1129 return objatt;
1026 } 1130 }
@@ -1155,7 +1259,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1155 + ", AttachmentPoint: " + AttachmentPt); 1259 + ", AttachmentPoint: " + AttachmentPt);
1156 1260
1157 // Save avatar attachment information 1261 // Save avatar attachment information
1158 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1262 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
1159 } 1263 }
1160 } 1264 }
1161 catch (Exception e) 1265 catch (Exception e)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 1a38619..f023e77 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -38,6 +38,8 @@ using NUnit.Framework;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Communications; 40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.CoreModules.Avatar.Attachments; 43using OpenSim.Region.CoreModules.Avatar.Attachments;
42using OpenSim.Region.CoreModules.Framework; 44using OpenSim.Region.CoreModules.Framework;
43using OpenSim.Region.CoreModules.Framework.EntityTransfer; 45using OpenSim.Region.CoreModules.Framework.EntityTransfer;
@@ -717,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
717 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 719 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
718 720
719 m_numberOfAttachEventsFired = 0; 721 m_numberOfAttachEventsFired = 0;
720 scene.IncomingCloseAgent(presence.UUID, false); 722 scene.CloseAgent(presence.UUID, false);
721 723
722 // Check that we can't retrieve this attachment from the scene. 724 // Check that we can't retrieve this attachment from the scene.
723 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 725 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
@@ -797,11 +799,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
797 } 799 }
798 800
799 [Test] 801 [Test]
800 public void TestSameSimulatorNeighbouringRegionsTeleport() 802 public void TestSameSimulatorNeighbouringRegionsTeleportV1()
801 { 803 {
802 TestHelpers.InMethod(); 804 TestHelpers.InMethod();
803// TestHelpers.EnableLogging(); 805// TestHelpers.EnableLogging();
804 806
807 BaseHttpServer httpServer = new BaseHttpServer(99999);
808 MainServer.AddHttpServer(httpServer);
809 MainServer.Instance = httpServer;
810
805 AttachmentsModule attModA = new AttachmentsModule(); 811 AttachmentsModule attModA = new AttachmentsModule();
806 AttachmentsModule attModB = new AttachmentsModule(); 812 AttachmentsModule attModB = new AttachmentsModule();
807 EntityTransferModule etmA = new EntityTransferModule(); 813 EntityTransferModule etmA = new EntityTransferModule();
@@ -830,14 +836,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
830 SceneHelpers.SetupSceneModules( 836 SceneHelpers.SetupSceneModules(
831 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); 837 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
832 838
839 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
840 lscm.ServiceVersion = "SIMULATION/0.1";
841
833 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 842 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
834 843
835 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 844 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
836 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 845 TestClient tc = new TestClient(acd, sceneA);
837 List<TestClient> destinationTestClients = new List<TestClient>(); 846 List<TestClient> destinationTestClients = new List<TestClient>();
838 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 847 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
839 848
840 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 849 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
841 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); 850 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
842 851
843 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); 852 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
@@ -895,5 +904,115 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
895 // Check events 904 // Check events
896 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 905 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
897 } 906 }
907
908 [Test]
909 public void TestSameSimulatorNeighbouringRegionsTeleportV2()
910 {
911 TestHelpers.InMethod();
912// TestHelpers.EnableLogging();
913
914 BaseHttpServer httpServer = new BaseHttpServer(99999);
915 MainServer.AddHttpServer(httpServer);
916 MainServer.Instance = httpServer;
917
918 AttachmentsModule attModA = new AttachmentsModule();
919 AttachmentsModule attModB = new AttachmentsModule();
920 EntityTransferModule etmA = new EntityTransferModule();
921 EntityTransferModule etmB = new EntityTransferModule();
922 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
923
924 IConfigSource config = new IniConfigSource();
925 IConfig modulesConfig = config.AddConfig("Modules");
926 modulesConfig.Set("EntityTransferModule", etmA.Name);
927 modulesConfig.Set("SimulationServices", lscm.Name);
928
929 modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
930
931 SceneHelpers sh = new SceneHelpers();
932 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
933 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
934
935 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
936 SceneHelpers.SetupSceneModules(
937 sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
938 SceneHelpers.SetupSceneModules(
939 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
940
941 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
942
943 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
944 TestClient tc = new TestClient(acd, sceneA);
945 List<TestClient> destinationTestClients = new List<TestClient>();
946 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
947
948 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
949 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
950
951 Assert.That(destinationTestClients.Count, Is.EqualTo(1));
952 Assert.That(destinationTestClients[0], Is.Not.Null);
953
954 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
955
956 sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
957 beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
958
959 Vector3 teleportPosition = new Vector3(10, 11, 12);
960 Vector3 teleportLookAt = new Vector3(20, 21, 22);
961
962 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
963 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
964 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
965 // Both these operations will occur on different threads and will wait for each other.
966 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
967 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
968 tc.OnTestClientSendRegionTeleport
969 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
970 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
971
972 m_numberOfAttachEventsFired = 0;
973 sceneA.RequestTeleportLocation(
974 beforeTeleportSp.ControllingClient,
975 sceneB.RegionInfo.RegionHandle,
976 teleportPosition,
977 teleportLookAt,
978 (uint)TeleportFlags.ViaLocation);
979
980 // Check attachments have made it into sceneB
981 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
982
983 // This is appearance data, as opposed to actually rezzed attachments
984 List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
985 Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
986 Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
987 Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
988 Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
989 Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
990
991 // This is the actual attachment
992 List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
993 Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
994 SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
995 Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
996 Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
997
998 Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
999
1000 // Check attachments have been removed from sceneA
1001 ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
1002
1003 // Since this is appearance data, it is still present on the child avatar!
1004 List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
1005 Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
1006 Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
1007
1008 // This is the actual attachment, which should no longer exist
1009 List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
1010 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
1011
1012 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
1013
1014 // Check events
1015 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
1016 }
898 } 1017 }
899} 1018}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index bc79944..dc16593 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 55
56 private int m_savetime = 5; // seconds to wait before saving changed appearance 56 private int m_savetime = 5; // seconds to wait before saving changed appearance
57 private int m_sendtime = 2; // seconds to wait before sending changed appearance 57 private int m_sendtime = 2; // seconds to wait before sending changed appearance
58 private bool m_reusetextures = false;
58 59
59 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates 60 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
60 private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); 61 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
@@ -73,6 +74,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
73 { 74 {
74 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
75 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures);
78
76 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
77 } 80 }
78 81
@@ -131,6 +134,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
131 client.OnRequestWearables += Client_OnRequestWearables; 134 client.OnRequestWearables += Client_OnRequestWearables;
132 client.OnSetAppearance += Client_OnSetAppearance; 135 client.OnSetAppearance += Client_OnSetAppearance;
133 client.OnAvatarNowWearing += Client_OnAvatarNowWearing; 136 client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
137 client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
134 } 138 }
135 139
136 #endregion 140 #endregion
@@ -184,27 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
184 // Process the visual params, this may change height as well 188 // Process the visual params, this may change height as well
185 if (visualParams != null) 189 if (visualParams != null)
186 { 190 {
187 // string[] visualParamsStrings = new string[visualParams.Length];
188 // for (int i = 0; i < visualParams.Length; i++)
189 // visualParamsStrings[i] = visualParams[i].ToString();
190 // m_log.DebugFormat(
191 // "[AVFACTORY]: Setting visual params for {0} to {1}",
192 // client.Name, string.Join(", ", visualParamsStrings));
193/*
194 float oldHeight = sp.Appearance.AvatarHeight;
195 changed = sp.Appearance.SetVisualParams(visualParams);
196
197 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
198 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
199 */
200// float oldoff = sp.Appearance.AvatarFeetOffset;
201// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
202 changed = sp.Appearance.SetVisualParams(visualParams); 191 changed = sp.Appearance.SetVisualParams(visualParams);
203// float off = sp.Appearance.AvatarFeetOffset;
204// Vector3 box = sp.Appearance.AvatarBoxSize;
205// if(oldoff != off || oldbox != box)
206// ((ScenePresence)sp).SetSize(box,off);
207
208 } 192 }
209 193
210 // Process the baked texture array 194 // Process the baked texture array
@@ -218,9 +202,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
218 202
219// WriteBakedTexturesReport(sp, m_log.DebugFormat); 203// WriteBakedTexturesReport(sp, m_log.DebugFormat);
220 204
205
221 // If bake textures are missing and this is not an NPC, request a rebake from client 206 // If bake textures are missing and this is not an NPC, request a rebake from client
222 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) 207 // rebake may messup caching, and should not be needed
223 RequestRebake(sp, true); 208
209
210// if (!UpdateBakedTextureCache(sp,cacheItems) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
211// RequestRebake(sp, true);
212
213 UpdateBakedTextureCache(sp, cacheItems);
224 214
225 // This appears to be set only in the final stage of the appearance 215 // This appears to be set only in the final stage of the appearance
226 // update transaction. In theory, we should be able to do an immediate 216 // update transaction. In theory, we should be able to do an immediate
@@ -373,119 +363,289 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
373 } 363 }
374 } 364 }
375 365
376 public bool ValidateBakedTextureCache(IScenePresence sp) 366 // called on textures update
367 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
377 { 368 {
378 bool defonly = true; // are we only using default textures 369 // uploaded baked textures will be in assets local cache
379 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 370 IAssetService cache = m_scene.AssetService;
380 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 371
381 WearableCacheItem[] wearableCache = null; 372 int validDirtyBakes = 0;
373 int hits = 0;
382 374
383 // Cache wearable data for teleport. 375 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
384 // Only makes sense if there's a bake module and a cache module 376 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
385 if (bakedModule != null && cache != null) 377
378 if (wearableCache == null)
386 { 379 {
387 try 380 wearableCache = WearableCacheItem.GetDefaultCacheItem();
381 }
382
383 // Process received baked textures
384 for (int i = 0; i < cacheItems.Length; i++)
385 {
386 int idx = (int)cacheItems[i].TextureIndex;
387 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
388
389 // No face
390 if (face == null)
388 { 391 {
389 wearableCache = bakedModule.Get(sp.UUID); 392 // for some reason viewer is cleaning this
393 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
394 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
395 wearableCache[idx].CacheId = UUID.Zero;
396 wearableCache[idx].TextureID = UUID.Zero;
397 wearableCache[idx].TextureAsset = null;
398 continue;
390 } 399 }
391 catch (Exception) 400 else
392 { 401 {
402 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
403 {
404 wearableCache[idx].CacheId = UUID.Zero;
405 wearableCache[idx].TextureID = UUID.Zero;
406 wearableCache[idx].TextureAsset = null;
407 continue;
408 }
393 409
394 } 410 if(sp.Appearance.Texture.FaceTextures[idx].TextureID == wearableCache[idx].TextureID)
395 if (wearableCache != null) 411 {
396 { 412 if(wearableCache[idx].CacheId != cacheItems[i].CacheId)
397 for (int i = 0; i < wearableCache.Length; i++) 413 {
414 wearableCache[idx].CacheId = cacheItems[i].CacheId;
415 validDirtyBakes++;
416
417 //assuming this can only happen if asset is in cache
418 }
419 hits++;
420 continue;
421 }
422
423 wearableCache[idx].TextureAsset = null;
424 if (cache != null)
425 wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString());
426
427 if (wearableCache[idx].TextureAsset != null)
428 {
429 wearableCache[idx].CacheId = cacheItems[i].CacheId;
430 wearableCache[idx].TextureID = sp.Appearance.Texture.FaceTextures[idx].TextureID;
431 validDirtyBakes++;
432 hits++;
433 }
434 else
398 { 435 {
399 cache.Cache(wearableCache[i].TextureAsset); 436 wearableCache[idx].CacheId = UUID.Zero;
437 wearableCache[idx].TextureID = UUID.Zero;
438 wearableCache[idx].TextureAsset = null;
439 continue;
400 } 440 }
401 } 441 }
402 } 442 }
403 /* 443
404 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 444 sp.Appearance.WearableCacheItems = wearableCache;
405 if (invService.GetRootFolder(userID) != null) 445
446 // if we got a full set of baked textures save all in BakedTextureModule
447
448 if (validDirtyBakes > 0 && hits == cacheItems.Length)
406 { 449 {
407 WearableCacheItem[] wearableCache = null; 450 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
408 if (bakedModule != null) 451 if (m_BakedTextureModule != null)
409 { 452 {
410 try 453 m_log.Debug("[UpdateBakedCache] uploading to bakedModule cache");
411 { 454
412 wearableCache = bakedModule.Get(userID); 455 WearableCacheItem[] toBakedModule = new WearableCacheItem[AvatarAppearance.BAKE_INDICES.Length];
413 appearance.WearableCacheItems = wearableCache; 456
414 appearance.WearableCacheItemsDirty = false; 457 for (int i = 0; i < cacheItems.Length; i++)
415 foreach (WearableCacheItem item in wearableCache)
416 {
417 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID;
418 }
419 }
420 catch (Exception)
421 { 458 {
422 459 int idx = (int)cacheItems[i].TextureIndex;
460 cacheItems[i].CacheId = wearableCache[idx].CacheId;
461 cacheItems[i].TextureID = wearableCache[idx].TextureID;
462 cacheItems[i].TextureAsset = wearableCache[idx].TextureAsset;
423 } 463 }
464 m_BakedTextureModule.Store(sp.UUID, cacheItems);
424 } 465 }
425 */ 466 }
426 467
427 // Process the texture entry 468 // debug
428 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 469 m_log.Debug("[UpdateBakedCache] cache hits: " + hits.ToString() + " changed entries: " + validDirtyBakes.ToString());
470/*
471 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
429 { 472 {
430 int idx = AvatarAppearance.BAKE_INDICES[i]; 473 int j = AvatarAppearance.BAKE_INDICES[iter];
431 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; 474 m_log.Debug("[UpdateBCache] {" + iter + "/" +
475 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
476 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
477 sp.Appearance.WearableCacheItems[j].TextureID);
478 }
479*/
480 return (hits == cacheItems.Length);
481 }
432 482
433 // No face, so lets check our baked service cache, teleport or login. 483 // called when we get a new root avatar
434 if (face == null) 484 public bool ValidateBakedTextureCache(IScenePresence sp)
485 {
486 int hits = 0;
487
488 lock (m_setAppearanceLock)
489 {
490 IAssetService cache = m_scene.AssetService;
491 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
492 WearableCacheItem[] bakedModuleCache = null;
493
494 if (cache == null)
495 return false;
496
497 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
498
499 // big debug
500 m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
501/*
502 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
435 { 503 {
436 if (wearableCache != null) 504 int j = AvatarAppearance.BAKE_INDICES[iter];
505 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
506 if (wearableCache == null)
437 { 507 {
438 // If we find the an appearance item, set it as the textureentry and the face 508 if (face != null)
439 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 509 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
440 if (searchitem != null)
441 {
442 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
443 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID;
444 face = sp.Appearance.Texture.FaceTextures[idx];
445 }
446 else 510 else
447 { 511 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
448 // if there is no texture entry and no baked cache, skip it
449 continue;
450 }
451 } 512 }
452 else 513 else
453 { 514 {
454 //No texture entry face and no cache. Skip this face. 515 if (face != null)
455 continue; 516 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
517 "}: cc-" +
518 wearableCache[j].CacheId + ", ct-" +
519 wearableCache[j].TextureID
520 );
521 else
522 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
523 "}: cc-" +
524 wearableCache[j].CacheId + ", ct-" +
525 wearableCache[j].TextureID
526 );
456 } 527 }
457 } 528 }
458 529*/
530 bool wearableCacheValid = false;
531 if (wearableCache == null)
532 {
533 wearableCache = WearableCacheItem.GetDefaultCacheItem();
534 }
535 else
536 {
537 // we may have received a full cache
538 // check same coerence and store
539 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
540 {
541 int idx = AvatarAppearance.BAKE_INDICES[i];
542 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
543 if (face != null && face.TextureID == wearableCache[idx].TextureID && wearableCache[idx].TextureAsset != null)
544 {
545 hits++;
546 wearableCache[idx].TextureAsset.Temporary = true;
547 wearableCache[idx].TextureAsset.Local = true;
548 cache.Store(wearableCache[idx].TextureAsset);
549 }
550 }
459 551
460// m_log.DebugFormat( 552 wearableCacheValid = (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
461// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", 553 if (wearableCacheValid)
462// face.TextureID, idx, client.Name, client.AgentId); 554 m_log.Debug("[ValidateBakedCache] have valid local cache");
555 }
463 556
464 // if the texture is one of the "defaults" then skip it 557 bool checkExternal = false;
465 // this should probably be more intelligent (skirt texture doesnt matter
466 // if the avatar isnt wearing a skirt) but if any of the main baked
467 // textures is default then the rest should be as well
468 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
469 continue;
470
471 defonly = false; // found a non-default texture reference
472 558
473 if (cache != null) 559 if (!wearableCacheValid)
474 { 560 {
475 if (!cache.Check(face.TextureID.ToString())) 561 // only use external bake module on login condition check
476 return false; 562// ScenePresence ssp = null;
563// if (sp is ScenePresence)
564 {
565// ssp = (ScenePresence)sp;
566// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
567// bakedModule != null;
568
569 // or do it anytime we dont have the cache
570 checkExternal = bakedModule != null;
571 }
477 } 572 }
478 else 573
574 if (checkExternal)
479 { 575 {
480 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) 576 hits = 0;
481 return false; 577 bool gotbacked = false;
578
579 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
580 try
581 {
582 bakedModuleCache = bakedModule.Get(sp.UUID);
583 }
584 catch (Exception)
585 {
586 bakedModuleCache = null;
587 }
588
589 if (bakedModuleCache != null)
590 {
591 m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
592
593 for (int i = 0; i < bakedModuleCache.Length; i++)
594 {
595 int j = (int)bakedModuleCache[i].TextureIndex;
596
597 if (bakedModuleCache[i].TextureAsset != null)
598 {
599 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
600 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
601 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
602 bakedModuleCache[i].TextureAsset.Temporary = true;
603 bakedModuleCache[i].TextureAsset.Local = true;
604 cache.Store(bakedModuleCache[i].TextureAsset);
605
606 }
607 }
608 gotbacked = true;
609 }
610
611 if (gotbacked)
612 {
613 // force the ones we got
614 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
615 {
616 int idx = AvatarAppearance.BAKE_INDICES[i];
617 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
618
619 if (sp.Appearance.Texture.FaceTextures[idx] == null)
620 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint)idx);
621 sp.Appearance.Texture.FaceTextures[idx].TextureID = wearableCache[idx].TextureID;
622 face = sp.Appearance.Texture.FaceTextures[idx];
623
624 // this should be removed
625 if (face.TextureID != UUID.Zero && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
626 hits++;
627 continue;
628 }
629 }
482 } 630 }
483 }
484 631
485// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 632 sp.Appearance.WearableCacheItems = wearableCache;
486 633
487 // If we only found default textures, then the appearance is not cached 634 }
488 return (defonly ? false : true); 635
636 // debug
637 m_log.DebugFormat("[ValidateBakedCache]: Completed texture check for {0} {1} with {2} hits", sp.Name, sp.UUID, hits);
638/*
639 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
640 {
641 int j = AvatarAppearance.BAKE_INDICES[iter];
642 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
643 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
644 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
645 sp.Appearance.WearableCacheItems[j].TextureID);
646 }
647*/
648 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
489 } 649 }
490 650
491 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 651 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
@@ -502,14 +662,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
502 if (face == null) 662 if (face == null)
503 continue; 663 continue;
504 664
505// m_log.DebugFormat(
506// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
507// face.TextureID, idx, client.Name, client.AgentId);
508
509 // if the texture is one of the "defaults" then skip it
510 // this should probably be more intelligent (skirt texture doesnt matter
511 // if the avatar isnt wearing a skirt) but if any of the main baked
512 // textures is default then the rest should be as well
513 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) 665 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
514 continue; 666 continue;
515 667
@@ -1068,6 +1220,61 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1068 QueueAppearanceSave(client.AgentId); 1220 QueueAppearanceSave(client.AgentId);
1069 } 1221 }
1070 } 1222 }
1223
1224 /// <summary>
1225 /// Respond to the cached textures request from the client
1226 /// </summary>
1227 /// <param name="client"></param>
1228 /// <param name="serial"></param>
1229 /// <param name="cachedTextureRequest"></param>
1230 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
1231 {
1232 // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
1233 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
1234
1235 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
1236 foreach (CachedTextureRequestArg request in cachedTextureRequest)
1237 {
1238 UUID texture = UUID.Zero;
1239 int index = request.BakedTextureIndex;
1240
1241 if (m_reusetextures)
1242 {
1243 // this is the most insanely dumb way to do this... however it seems to
1244 // actually work. if the appearance has been reset because wearables have
1245 // changed then the texture entries are zero'd out until the bakes are
1246 // uploaded. on login, if the textures exist in the cache (eg if you logged
1247 // into the simulator recently, then the appearance will pull those and send
1248 // them back in the packet and you won't have to rebake. if the textures aren't
1249 // in the cache then the intial makeroot() call in scenepresence will zero
1250 // them out.
1251 //
1252 // a better solution (though how much better is an open question) is to
1253 // store the hashes in the appearance and compare them. Thats's coming.
1254
1255 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
1256 if (face != null)
1257 texture = face.TextureID;
1258
1259 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1260 }
1261
1262 CachedTextureResponseArg response = new CachedTextureResponseArg();
1263 response.BakedTextureIndex = index;
1264 response.BakedTextureID = texture;
1265 response.HostName = null;
1266
1267 cachedTextureResponse.Add(response);
1268 }
1269
1270 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1271 // The serial number appears to be used to match requests and responses
1272 // in the texture transaction. We just send back the serial number
1273 // that was provided in the request. The viewer bumps this for us.
1274 client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
1275 }
1276
1277
1071 #endregion 1278 #endregion
1072 1279
1073 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction) 1280 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 174642d..dcfc630 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -32,6 +32,7 @@ using log4net;
32using Nini.Config; 32using Nini.Config;
33using Mono.Addins; 33using Mono.Addins;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
@@ -103,6 +104,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 104
104 public virtual void RegionLoaded(Scene scene) 105 public virtual void RegionLoaded(Scene scene)
105 { 106 {
107 if (!m_enabled)
108 return;
109
110 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
111
112 if (featuresModule != null)
113 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
114
106 } 115 }
107 116
108 public virtual void RemoveRegion(Scene scene) 117 public virtual void RemoveRegion(Scene scene)
@@ -207,6 +216,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
207 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, 216 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
208 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); 217 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
209 218
219 bool checkParcelHide = false;
220 UUID sourceParcelID = UUID.Zero;
221 Vector3 hidePos = fromPos;
222
210 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 223 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
211 224
212 switch (sourceType) 225 switch (sourceType)
@@ -223,20 +236,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
223 fromName = avatar.Name; 236 fromName = avatar.Name;
224 fromID = c.Sender.AgentId; 237 fromID = c.Sender.AgentId;
225 if (avatar.GodLevel >= 200) 238 if (avatar.GodLevel >= 200)
226 { 239 { // let gods speak to outside or things may get confusing
227 fromNamePrefix = m_adminPrefix; 240 fromNamePrefix = m_adminPrefix;
241 checkParcelHide = false;
242 }
243 else
244 {
245 checkParcelHide = true;
228 } 246 }
229 destination = UUID.Zero; // Avatars cant "SayTo" 247 destination = UUID.Zero; // Avatars cant "SayTo"
230 ownerID = c.Sender.AgentId; 248 ownerID = c.Sender.AgentId;
231 249
250 hidePos = fromPos;
232 break; 251 break;
233 252
234 case ChatSourceType.Object: 253 case ChatSourceType.Object:
235 fromID = c.SenderUUID; 254 fromID = c.SenderUUID;
236 255
237 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 256 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
257 {
238 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 258 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
239 259 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
260 {
261 checkParcelHide = true;
262 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
263 }
264 }
240 break; 265 break;
241 } 266 }
242 267
@@ -249,13 +274,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
249// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType); 274// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
250 275
251 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 276 HashSet<UUID> receiverIDs = new HashSet<UUID>();
252 277
278 if (checkParcelHide)
279 {
280 checkParcelHide = false;
281 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
282 {
283 ILandObject srcland = (scene as Scene).LandChannel.GetLandObject(hidePos.X, hidePos.Y);
284 if (srcland != null && !srcland.LandData.SeeAVs)
285 {
286 sourceParcelID = srcland.LandData.GlobalID;
287 checkParcelHide = true;
288 }
289 }
290 }
291
253 foreach (Scene s in m_scenes) 292 foreach (Scene s in m_scenes)
254 { 293 {
255 // This should use ForEachClient, but clients don't have a position. 294 // This should use ForEachClient, but clients don't have a position.
256 // If camera is moved into client, then camera position can be used 295 // If camera is moved into client, then camera position can be used
257 // MT: No, it can't, as chat is heard from the avatar position, not 296 // MT: No, it can't, as chat is heard from the avatar position, not
258 // the camera position. 297 // the camera position.
298
259 s.ForEachScenePresence( 299 s.ForEachScenePresence(
260 delegate(ScenePresence presence) 300 delegate(ScenePresence presence)
261 { 301 {
@@ -268,6 +308,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
268 // perfect, but it will do. For now. Better 308 // perfect, but it will do. For now. Better
269 // than the prior behavior of muting all 309 // than the prior behavior of muting all
270 // objects on a parcel with access restrictions 310 // objects on a parcel with access restrictions
311 if (checkParcelHide)
312 {
313 if (sourceParcelID != Presencecheck.LandData.GlobalID && presence.GodLevel < 200)
314 return;
315 }
271 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) 316 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
272 { 317 {
273 if (destination != UUID.Zero) 318 if (destination != UUID.Zero)
@@ -372,21 +417,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 417 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
373 string message, ChatSourceType src, bool ignoreDistance) 418 string message, ChatSourceType src, bool ignoreDistance)
374 { 419 {
375 // don't send chat to child agents 420 if (presence.LifecycleState != ScenePresenceState.Running)
376 if (presence.IsChildAgent) return false; 421 return false;
377
378 Vector3 fromRegionPos = fromPos + regionPos;
379 Vector3 toRegionPos = presence.AbsolutePosition +
380 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
381 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
382 422
383 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 423 if (!ignoreDistance)
384
385 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
386 type == ChatTypeEnum.Say && dis > m_saydistance ||
387 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
388 { 424 {
389 return false; 425 Vector3 fromRegionPos = fromPos + regionPos;
426 Vector3 toRegionPos = presence.AbsolutePosition +
427 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
428 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
429
430 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
431
432 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
433 type == ChatTypeEnum.Say && dis > m_saydistance ||
434 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
435 {
436 return false;
437 }
390 } 438 }
391 439
392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 440 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
@@ -426,5 +474,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
426 Timers.Remove(target); 474 Timers.Remove(target);
427 Timer.Dispose(); 475 Timer.Dispose();
428 } 476 }
477 #region SimulatorFeaturesRequest
478
479 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
480
481 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
482 {
483 OSD extras = new OSDMap();
484 if (features.ContainsKey("OpenSimExtras"))
485 extras = features["OpenSimExtras"];
486 else
487 features["OpenSimExtras"] = extras;
488
489 if (m_SayRange == null)
490 {
491 // Do this only once
492 m_SayRange = new OSDInteger(m_saydistance);
493 m_WhisperRange = new OSDInteger(m_whisperdistance);
494 m_ShoutRange = new OSDInteger(m_shoutdistance);
495 }
496
497 ((OSDMap)extras)["say-range"] = m_SayRange;
498 ((OSDMap)extras)["whisper-range"] = m_WhisperRange;
499 ((OSDMap)extras)["shout-range"] = m_ShoutRange;
500
501 }
502
503 #endregion
429 } 504 }
430} 505}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 8056030..b693f2d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
371 foreach (string fid in outstanding) 371 foreach (string fid in outstanding)
372 { 372 {
373 UUID fromAgentID; 373 UUID fromAgentID;
374 string firstname = "Unknown", lastname = "User"; 374 string firstname = "Unknown", lastname = "UserFMSFOIN";
375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) 375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
376 { 376 {
377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); 377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
@@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
397 397
398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
399 { 399 {
400 first = "Unknown"; last = "User"; 400 first = "Unknown"; last = "UserFMGAI";
401 if (!UUID.TryParse(fid, out agentID)) 401 if (!UUID.TryParse(fid, out agentID))
402 return false; 402 return false;
403 403
@@ -498,6 +498,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
498 498
499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
500 { 500 {
501 //m_log.DebugFormat("[FRIENDS]: Entering StatusNotify for {0}", userID);
502
501 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend); 503 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend);
502 List<string> remoteFriendStringIds = new List<string>(); 504 List<string> remoteFriendStringIds = new List<string>();
503 foreach (string friendStringId in friendStringIds) 505 foreach (string friendStringId in friendStringIds)
@@ -523,12 +525,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
523 foreach (PresenceInfo friendSession in friendSessions) 525 foreach (PresenceInfo friendSession in friendSessions)
524 { 526 {
525 // let's guard against sessions-gone-bad 527 // let's guard against sessions-gone-bad
526 if (friendSession.RegionID != UUID.Zero) 528 if (friendSession != null && friendSession.RegionID != UUID.Zero)
527 { 529 {
530 //m_log.DebugFormat("[FRIENDS]: Get region {0}", friendSession.RegionID);
528 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 531 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
529 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 532 if (region != null)
530 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); 533 {
534 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
535 }
531 } 536 }
537 //else
538 // m_log.DebugFormat("[FRIENDS]: friend session is null or the region is UUID.Zero");
532 } 539 }
533 } 540 }
534 541
@@ -685,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
685 // 692 //
686 693
687 // Try local 694 // Try local
688 if (LocalFriendshipTerminated(exfriendID)) 695 if (LocalFriendshipTerminated(client.AgentId, exfriendID))
689 return; 696 return;
690 697
691 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); 698 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() });
@@ -827,13 +834,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
827 return false; 834 return false;
828 } 835 }
829 836
830 public bool LocalFriendshipTerminated(UUID exfriendID) 837 public bool LocalFriendshipTerminated(UUID userID, UUID exfriendID)
831 { 838 {
832 IClientAPI friendClient = LocateClientObject(exfriendID); 839 IClientAPI friendClient = LocateClientObject(exfriendID);
833 if (friendClient != null) 840 if (friendClient != null)
834 { 841 {
835 // the friend in this sim as root agent 842 // the friend in this sim as root agent
836 friendClient.SendTerminateFriend(exfriendID); 843 friendClient.SendTerminateFriend(userID);
837 // update local cache 844 // update local cache
838 RecacheFriends(friendClient); 845 RecacheFriends(friendClient);
839 // we're done 846 // we're done
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 637beef..ff87ece 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -42,19 +42,27 @@ using log4net;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Friends 43namespace OpenSim.Region.CoreModules.Avatar.Friends
44{ 44{
45 public class FriendsRequestHandler : BaseStreamHandler 45 public class FriendsRequestHandler : BaseStreamHandlerBasicDOSProtector
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private FriendsModule m_FriendsModule; 49 private FriendsModule m_FriendsModule;
50 50
51 public FriendsRequestHandler(FriendsModule fmodule) 51 public FriendsRequestHandler(FriendsModule fmodule)
52 : base("POST", "/friends") 52 : base("POST", "/friends", new BasicDosProtectorOptions()
53 {
54 AllowXForwardedFor = true,
55 ForgetTimeSpan = TimeSpan.FromMinutes(2),
56 MaxRequestsInTimeframe = 20,
57 ReportingName = "FRIENDSDOSPROTECTOR",
58 RequestTimeSpan = TimeSpan.FromSeconds(5),
59 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
60 })
53 { 61 {
54 m_FriendsModule = fmodule; 62 m_FriendsModule = fmodule;
55 } 63 }
56 64
57 public override byte[] Handle( 65 protected override byte[] ProcessRequest(
58 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 67 {
60 StreamReader sr = new StreamReader(requestData); 68 StreamReader sr = new StreamReader(requestData);
@@ -193,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
193 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 201 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
194 return FailureResult(); 202 return FailureResult();
195 203
196 if (m_FriendsModule.LocalFriendshipTerminated(toID)) 204 if (m_FriendsModule.LocalFriendshipTerminated(fromID, toID))
197 return SuccessResult(); 205 return SuccessResult();
198 206
199 return FailureResult(); 207 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index bf5c0bb..d00945e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -183,6 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
183 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) 183 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
184 { 184 {
185 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>(); 185 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
186 m_log.DebugFormat("[HGFRIENDS MODULE]: caching {0}", finfo.Friend);
186 uMan.AddUser(id, url + ";" + first + " " + last); 187 uMan.AddUser(id, url + ";" + first + " " + last);
187 } 188 }
188 } 189 }
@@ -251,7 +252,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
251 252
252 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 253 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
253 { 254 {
254// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID); 255 //m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
255 256
256 // First, let's divide the friends on a per-domain basis 257 // First, let's divide the friends on a per-domain basis
257 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>(); 258 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
@@ -293,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
293 294
294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 295 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
295 { 296 {
296 first = "Unknown"; last = "User"; 297 first = "Unknown"; last = "UserHGGAI";
297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) 298 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
298 return true; 299 return true;
299 300
@@ -349,7 +350,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
349 350
350 public override FriendInfo[] GetFriendsFromService(IClientAPI client) 351 public override FriendInfo[] GetFriendsFromService(IClientAPI client)
351 { 352 {
352// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name); 353 // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name);
353 Boolean agentIsLocal = true; 354 Boolean agentIsLocal = true;
354 if (UserManagementModule != null) 355 if (UserManagementModule != null)
355 agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId); 356 agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId);
@@ -362,13 +363,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
362 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); 363 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
363 if (agentClientCircuit != null) 364 if (agentClientCircuit != null)
364 { 365 {
365 //[XXX] string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); 366 // Note that this is calling a different interface than base; this one calls with a string param!
366
367 finfos = FriendsService.GetFriends(client.AgentId.ToString()); 367 finfos = FriendsService.GetFriends(client.AgentId.ToString());
368 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString()); 368 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString());
369 } 369 }
370 370
371// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name); 371 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
372 372
373 return finfos; 373 return finfos;
374 } 374 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index fa8c3f3..adb838c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -26,27 +26,25 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.Framework.Interfaces;
35using System;
36using System.Reflection;
37using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
38using System.Collections.Specialized; 31using System.Collections.Specialized;
39using System.Reflection;
40using System.IO; 32using System.IO;
33using System.Reflection;
41using System.Web; 34using System.Web;
42using System.Xml; 35using System.Xml;
43using log4net; 36using log4net;
44using Mono.Addins; 37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
45using OpenMetaverse.Messages.Linden; 40using OpenMetaverse.Messages.Linden;
46using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42using OpenSim.Framework;
47using OpenSim.Framework.Capabilities; 43using OpenSim.Framework.Capabilities;
48using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
49using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps; 48using Caps = OpenSim.Framework.Capabilities.Caps;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
@@ -127,9 +125,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
127 { 125 {
128 string uri = "/CAPS/" + UUID.Random(); 126 string uri = "/CAPS/" + UUID.Random();
129 127
130 caps.RegisterHandler("UntrustedSimulatorMessage", 128 caps.RegisterHandler(
131 new RestStreamHandler("POST", uri, 129 "UntrustedSimulatorMessage",
132 HandleUntrustedSimulatorMessage)); 130 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null));
133 } 131 }
134 132
135 private string HandleUntrustedSimulatorMessage(string request, 133 private string HandleUntrustedSimulatorMessage(string request,
@@ -278,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
278 if (sp.IsChildAgent) 276 if (sp.IsChildAgent)
279 return; 277 return;
280 sp.ControllingClient.Kick(reason); 278 sp.ControllingClient.Kick(reason);
281 sp.Scene.IncomingCloseAgent(sp.UUID, true); 279 sp.Scene.CloseAgent(sp.UUID, true);
282 } 280 }
283 281
284 private void OnIncomingInstantMessage(GridInstantMessage msg) 282 private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 1627f6c..b321adb 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -392,7 +392,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
392 gim.fromAgentName = fromAgentName; 392 gim.fromAgentName = fromAgentName;
393 gim.fromGroup = fromGroup; 393 gim.fromGroup = fromGroup;
394 gim.imSessionID = imSessionID.Guid; 394 gim.imSessionID = imSessionID.Guid;
395 gim.RegionID = UUID.Zero.Guid; // RegionID.Guid; 395 gim.RegionID = RegionID.Guid;
396 gim.timestamp = timestamp; 396 gim.timestamp = timestamp;
397 gim.toAgentID = toAgentID.Guid; 397 gim.toAgentID = toAgentID.Guid;
398 gim.message = message; 398 gim.message = message;
@@ -728,7 +728,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
728 gim["position_x"] = msg.Position.X.ToString(); 728 gim["position_x"] = msg.Position.X.ToString();
729 gim["position_y"] = msg.Position.Y.ToString(); 729 gim["position_y"] = msg.Position.Y.ToString();
730 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
731 gim["region_id"] = msg.RegionID.ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733 if (m_MessageKey != String.Empty) 733 if (m_MessageKey != String.Empty)
734 gim["message_key"] = m_MessageKey; 734 gim["message_key"] = m_MessageKey;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 659b178..5a8544e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -67,10 +67,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
67 /// </summary> 67 /// </summary>
68 protected bool m_merge; 68 protected bool m_merge;
69 69
70 /// <value> 70 protected IInventoryService m_InventoryService;
71 /// We only use this to request modules 71 protected IAssetService m_AssetService;
72 /// </value> 72 protected IUserAccountService m_UserAccountService;
73 protected Scene m_scene;
74 73
75 /// <value> 74 /// <value>
76 /// The stream from which the inventory archive will be loaded. 75 /// The stream from which the inventory archive will be loaded.
@@ -118,9 +117,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
118 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>(); 117 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
119 118
120 public InventoryArchiveReadRequest( 119 public InventoryArchiveReadRequest(
121 Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) 120 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
122 : this( 121 : this(
123 scene, 122 inv,
123 assets,
124 uacc,
124 userInfo, 125 userInfo,
125 invPath, 126 invPath,
126 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress), 127 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress),
@@ -129,9 +130,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
129 } 130 }
130 131
131 public InventoryArchiveReadRequest( 132 public InventoryArchiveReadRequest(
132 Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge) 133 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
133 { 134 {
134 m_scene = scene; 135 m_InventoryService = inv;
136 m_AssetService = assets;
137 m_UserAccountService = uacc;
135 m_merge = merge; 138 m_merge = merge;
136 m_userInfo = userInfo; 139 m_userInfo = userInfo;
137 m_invPath = invPath; 140 m_invPath = invPath;
@@ -162,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
162 165
163 List<InventoryFolderBase> folderCandidates 166 List<InventoryFolderBase> folderCandidates
164 = InventoryArchiveUtils.FindFoldersByPath( 167 = InventoryArchiveUtils.FindFoldersByPath(
165 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); 168 m_InventoryService, m_userInfo.PrincipalID, m_invPath);
166 169
167 if (folderCandidates.Count == 0) 170 if (folderCandidates.Count == 0)
168 { 171 {
@@ -297,7 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
297 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); 300 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
298 List<InventoryFolderBase> folderCandidates 301 List<InventoryFolderBase> folderCandidates
299 = InventoryArchiveUtils.FindFoldersByPath( 302 = InventoryArchiveUtils.FindFoldersByPath(
300 m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); 303 m_InventoryService, m_userInfo.PrincipalID, plainPath);
301 304
302 if (folderCandidates.Count != 0) 305 if (folderCandidates.Count != 0)
303 { 306 {
@@ -380,7 +383,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
380 = new InventoryFolderBase( 383 = new InventoryFolderBase(
381 newFolderId, newFolderName, m_userInfo.PrincipalID, 384 newFolderId, newFolderName, m_userInfo.PrincipalID,
382 (short)AssetType.Unknown, destFolder.ID, 1); 385 (short)AssetType.Unknown, destFolder.ID, 1);
383 m_scene.InventoryService.AddFolder(destFolder); 386 m_InventoryService.AddFolder(destFolder);
384 387
385 // Record that we have now created this folder 388 // Record that we have now created this folder
386 iarPathExisting += rawDirsToCreate[i] + "/"; 389 iarPathExisting += rawDirsToCreate[i] + "/";
@@ -406,7 +409,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
406 // Don't use the item ID that's in the file 409 // Don't use the item ID that's in the file
407 item.ID = UUID.Random(); 410 item.ID = UUID.Random();
408 411
409 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); 412 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
410 if (UUID.Zero != ospResolvedId) // The user exists in this grid 413 if (UUID.Zero != ospResolvedId) // The user exists in this grid
411 { 414 {
412// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); 415// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
@@ -418,7 +421,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 item.CreatorId = ospResolvedId.ToString(); 421 item.CreatorId = ospResolvedId.ToString();
419 item.CreatorData = string.Empty; 422 item.CreatorData = string.Empty;
420 } 423 }
421 else if (item.CreatorData == null || item.CreatorData == String.Empty) 424 else if (string.IsNullOrEmpty(item.CreatorData))
422 { 425 {
423 item.CreatorId = m_userInfo.PrincipalID.ToString(); 426 item.CreatorId = m_userInfo.PrincipalID.ToString();
424// item.CreatorIdAsUuid = new UUID(item.CreatorId); 427// item.CreatorIdAsUuid = new UUID(item.CreatorId);
@@ -436,7 +439,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
436 // relying on native tar tools. 439 // relying on native tar tools.
437 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; 440 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
438 441
439 m_scene.AddInventoryItem(item); 442 if (!m_InventoryService.AddItem(item))
443 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
440 444
441 return item; 445 return item;
442 } 446 }
@@ -518,7 +522,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
518 522
519 foreach (SceneObjectGroup sog in sceneObjects) 523 foreach (SceneObjectGroup sog in sceneObjects)
520 foreach (SceneObjectPart sop in sog.Parts) 524 foreach (SceneObjectPart sop in sog.Parts)
521 if (sop.CreatorData == null || sop.CreatorData == "") 525 if (string.IsNullOrEmpty(sop.CreatorData))
522 sop.CreatorID = m_creatorIdForAssetId[assetId]; 526 sop.CreatorID = m_creatorIdForAssetId[assetId];
523 527
524 if (coa != null) 528 if (coa != null)
@@ -533,7 +537,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
533 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); 537 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
534 asset.Data = data; 538 asset.Data = data;
535 539
536 m_scene.AssetService.Store(asset); 540 m_AssetService.Store(asset);
537 541
538 return true; 542 return true;
539 } 543 }
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/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index f4f9e2d..ea660bd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
294 294
295 try 295 try
296 { 296 {
297 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge); 297 request = new InventoryArchiveReadRequest(m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge);
298 } 298 }
299 catch (EntryPointNotFoundException e) 299 catch (EntryPointNotFoundException e)
300 { 300 {
@@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
342 342
343 try 343 try
344 { 344 {
345 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); 345 request = new InventoryArchiveReadRequest(m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge);
346 } 346 }
347 catch (EntryPointNotFoundException e) 347 catch (EntryPointNotFoundException e)
348 { 348 {
@@ -538,7 +538,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538 } 538 }
539 catch (Exception e) 539 catch (Exception e)
540 { 540 {
541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); 541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
542 return null; 542 return null;
543 } 543 }
544 */ 544 */
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index 95f562e..08f199a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
229 229
230 { 230 {
231 // Test replication of path1 231 // Test replication of path1
232 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 232 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
233 .ReplicateArchivePathToUserInventory( 233 .ReplicateArchivePathToUserInventory(
234 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 234 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
235 foldersCreated, nodesLoaded); 235 foldersCreated, nodesLoaded);
@@ -246,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
246 246
247 { 247 {
248 // Test replication of path2 248 // Test replication of path2
249 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 249 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
250 .ReplicateArchivePathToUserInventory( 250 .ReplicateArchivePathToUserInventory(
251 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 251 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
252 foldersCreated, nodesLoaded); 252 foldersCreated, nodesLoaded);
@@ -291,8 +291,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
292 292
293 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 293 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
294 294
295 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 295 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
296 .ReplicateArchivePathToUserInventory( 296 .ReplicateArchivePathToUserInventory(
297 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 297 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
@@ -342,8 +342,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
343 343
344 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 344 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
345 345
346 new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true) 346 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true)
347 .ReplicateArchivePathToUserInventory( 347 .ReplicateArchivePathToUserInventory(
348 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 348 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
index 5e7e24c..b85739e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
86 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 86 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
87 87
88 InventoryArchiveReadRequest iarr 88 InventoryArchiveReadRequest iarr
89 = new InventoryArchiveReadRequest(null, null, null, (Stream)null, false); 89 = new InventoryArchiveReadRequest(null, null, null, null, null, (Stream)null, false);
90 iarr.LoadControlFile(filePath, data); 90 iarr.LoadControlFile(filePath, data);
91 91
92 Assert.That(iarr.ControlFileLoaded, Is.True); 92 Assert.That(iarr.ControlFileLoaded, Is.True);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index f122d00..03aaaac 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -47,10 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
47 47
48 /// <summary> 48 /// <summary>
49 private List<Scene> m_Scenelist = new List<Scene>(); 49 private List<Scene> m_Scenelist = new List<Scene>();
50// private Dictionary<UUID, Scene> m_AgentRegions =
51// new Dictionary<UUID, Scene>();
52 50
53 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule;
54 private bool m_Enabled = true; 52 private bool m_Enabled = true;
55 53
56 #region Region Module interface 54 #region Region Module interface
@@ -81,9 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
81// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79// scene.RegisterModuleInterface<IInventoryTransferModule>(this);
82 80
83 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
84// scene.EventManager.OnClientClosed += ClientLoggedOut;
85 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 82 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
86// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
87 } 83 }
88 84
89 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
@@ -96,11 +92,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only"); 92 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only");
97 m_Enabled = false; 93 m_Enabled = false;
98 94
99 m_Scenelist.Clear(); 95// m_Scenelist.Clear();
100 scene.EventManager.OnNewClient -= OnNewClient; 96// scene.EventManager.OnNewClient -= OnNewClient;
101// scene.EventManager.OnClientClosed -= ClientLoggedOut;
102 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 97 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
103// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
104 } 98 }
105 } 99 }
106 } 100 }
@@ -108,9 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
108 public void RemoveRegion(Scene scene) 102 public void RemoveRegion(Scene scene)
109 { 103 {
110 scene.EventManager.OnNewClient -= OnNewClient; 104 scene.EventManager.OnNewClient -= OnNewClient;
111// scene.EventManager.OnClientClosed -= ClientLoggedOut;
112 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 105 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
113// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
114 m_Scenelist.Remove(scene); 106 m_Scenelist.Remove(scene);
115 } 107 }
116 108
@@ -139,11 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
139 // Inventory giving is conducted via instant message 131 // Inventory giving is conducted via instant message
140 client.OnInstantMessage += OnInstantMessage; 132 client.OnInstantMessage += OnInstantMessage;
141 } 133 }
142
143// protected void OnSetRootAgentScene(UUID id, Scene scene)
144// {
145// m_AgentRegions[id] = scene;
146// }
147 134
148 private Scene FindClientScene(UUID agentId) 135 private Scene FindClientScene(UUID agentId)
149 { 136 {
@@ -162,8 +149,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
162 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
163 { 150 {
164// m_log.DebugFormat( 151// m_log.DebugFormat(
165// "[INVENTORY TRANSFER]: {0} IM type received from {1}", 152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
166// (InstantMessageDialog)im.dialog, client.Name); 153// (InstantMessageDialog)im.dialog, client.Name,
154// im.fromAgentID, im.fromAgentName, im.toAgentID);
167 155
168 Scene scene = FindClientScene(client.AgentId); 156 Scene scene = FindClientScene(client.AgentId);
169 157
@@ -188,9 +176,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
188 { 176 {
189 UUID folderID = new UUID(im.binaryBucket, 1); 177 UUID folderID = new UUID(im.binaryBucket, 1);
190 178
191 m_log.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} "+ 179 m_log.DebugFormat(
192 "into agent {1}'s inventory", 180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
193 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
194 182
195 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
196 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
@@ -213,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
213 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 201 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
214 202
215 // HACK!! 203 // HACK!!
216 // Insert the ID of the copied item into the IM so that we know which item to move to trash if it 204 // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it
217 // is rejected. 205 // is rejected.
218 // XXX: This is probably a misuse of the session ID slot. 206 // XXX: This is probably a misuse of the session ID slot.
219 im.imSessionID = copyID.Guid; 207 im.imSessionID = copyID.Guid;
@@ -425,7 +413,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
425 { 413 {
426 folder = new InventoryFolderBase(inventoryID, client.AgentId); 414 folder = new InventoryFolderBase(inventoryID, client.AgentId);
427 folder = invService.GetFolder(folder); 415 folder = invService.GetFolder(folder);
428 416
429 if (folder != null & trashFolder != null) 417 if (folder != null & trashFolder != null)
430 { 418 {
431 previousParentFolderID = folder.ParentID; 419 previousParentFolderID = folder.ParentID;
@@ -477,76 +465,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
477 } 465 }
478 } 466 }
479 467
480// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
481// {
482// if (!m_AgentRegions.ContainsKey(agentID))
483// {
484// // Since we can get here two ways, we need to scan
485// // the scenes here. This is somewhat more expensive
486// // but helps avoid a nasty bug
487// //
488//
489// foreach (Scene s in m_Scenelist)
490// {
491// ScenePresence presence;
492//
493// if (s.TryGetScenePresence(agentID, out presence))
494// {
495// // If the agent is in this scene, then we
496// // are being called twice in a single
497// // teleport. This is wasteful of cycles
498// // but harmless due to this 2nd level check
499// //
500// // If the agent is found in another scene
501// // then the list wasn't current
502// //
503// // If the agent is totally unknown, then what
504// // are we even doing here??
505// //
506// if (s == scene)
507// {
508// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
509// return true;
510// }
511// else
512// {
513// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
514// return false;
515// }
516// }
517// }
518// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
519// return true;
520// }
521//
522// // The agent is left in current Scene, so we must be
523// // going to another instance
524// //
525// if (m_AgentRegions[agentID] == scene)
526// {
527// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
528// m_AgentRegions.Remove(agentID);
529// return true;
530// }
531//
532// // Another region has claimed the agent
533// //
534// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
535// return false;
536// }
537//
538// public void ClientLoggedOut(UUID agentID, Scene scene)
539// {
540// if (m_AgentRegions.ContainsKey(agentID))
541// m_AgentRegions.Remove(agentID);
542// }
543
544 /// <summary> 468 /// <summary>
545 /// 469 ///
546 /// </summary> 470 /// </summary>
547 /// <param name="msg"></param> 471 /// <param name="im"></param>
548 private void OnGridInstantMessage(GridInstantMessage im) 472 private void OnGridInstantMessage(GridInstantMessage im)
549 { 473 {
474 // Check if it's a type of message that we should handle
475 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
476 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
477 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
478 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
479 return;
480
481 m_log.DebugFormat(
482 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
483 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
484
550 // Check if this is ours to handle 485 // Check if this is ours to handle
551 // 486 //
552 Scene scene = FindClientScene(new UUID(im.toAgentID)); 487 Scene scene = FindClientScene(new UUID(im.toAgentID));
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
new file mode 100644
index 0000000..162a0c3
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -0,0 +1,449 @@
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.Reflection;
31using log4net.Config;
32using Nini.Config;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenMetaverse.Assets;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
45{
46 [TestFixture]
47 public class InventoryTransferModuleTests : OpenSimTestCase
48 {
49 protected TestScene m_scene;
50
51 [SetUp]
52 public override void SetUp()
53 {
54 base.SetUp();
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("Messaging");
58 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
59
60 m_scene = new SceneHelpers().SetupScene();
61 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
62 }
63
64 [Test]
65 public void TestAcceptGivenItem()
66 {
67// TestHelpers.EnableLogging();
68
69 UUID initialSessionId = TestHelpers.ParseTail(0x10);
70 UUID itemId = TestHelpers.ParseTail(0x100);
71 UUID assetId = TestHelpers.ParseTail(0x200);
72
73 UserAccount ua1
74 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
75 UserAccount ua2
76 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
77
78 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
79 TestClient giverClient = (TestClient)giverSp.ControllingClient;
80
81 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
82 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
83
84 // Create the object to test give
85 InventoryItemBase originalItem
86 = UserInventoryHelpers.CreateInventoryItem(
87 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
88
89 byte[] giveImBinaryBucket = new byte[17];
90 byte[] itemIdBytes = itemId.GetBytes();
91 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
92
93 GridInstantMessage giveIm
94 = new GridInstantMessage(
95 m_scene,
96 giverSp.UUID,
97 giverSp.Name,
98 receiverSp.UUID,
99 (byte)InstantMessageDialog.InventoryOffered,
100 false,
101 "inventory offered msg",
102 initialSessionId,
103 false,
104 Vector3.Zero,
105 giveImBinaryBucket,
106 true);
107
108 giverClient.HandleImprovedInstantMessage(giveIm);
109
110 // These details might not all be correct.
111 GridInstantMessage acceptIm
112 = new GridInstantMessage(
113 m_scene,
114 receiverSp.UUID,
115 receiverSp.Name,
116 giverSp.UUID,
117 (byte)InstantMessageDialog.InventoryAccepted,
118 false,
119 "inventory accepted msg",
120 initialSessionId,
121 false,
122 Vector3.Zero,
123 null,
124 true);
125
126 receiverClient.HandleImprovedInstantMessage(acceptIm);
127
128 // Test for item remaining in the giver's inventory (here we assume a copy item)
129 // TODO: Test no-copy items.
130 InventoryItemBase originalItemAfterGive
131 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
132
133 Assert.That(originalItemAfterGive, Is.Not.Null);
134 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
135
136 // Test for item successfully making it into the receiver's inventory
137 InventoryItemBase receivedItem
138 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
139
140 Assert.That(receivedItem, Is.Not.Null);
141 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
142
143 // Test that on a delete, item still exists and is accessible for the giver.
144 m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List<UUID>() { receivedItem.ID });
145
146 InventoryItemBase originalItemAfterDelete
147 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
148
149 Assert.That(originalItemAfterDelete, Is.Not.Null);
150
151 // TODO: Test scenario where giver deletes their item first.
152 }
153
154 /// <summary>
155 /// Test user rejection of a given item.
156 /// </summary>
157 /// <remarks>
158 /// A rejected item still ends up in the user's trash folder.
159 /// </remarks>
160 [Test]
161 public void TestRejectGivenItem()
162 {
163// TestHelpers.EnableLogging();
164
165 UUID initialSessionId = TestHelpers.ParseTail(0x10);
166 UUID itemId = TestHelpers.ParseTail(0x100);
167 UUID assetId = TestHelpers.ParseTail(0x200);
168
169 UserAccount ua1
170 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
171 UserAccount ua2
172 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
173
174 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
175 TestClient giverClient = (TestClient)giverSp.ControllingClient;
176
177 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
178 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
179
180 // Create the object to test give
181 InventoryItemBase originalItem
182 = UserInventoryHelpers.CreateInventoryItem(
183 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
184
185 GridInstantMessage receivedIm = null;
186 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
187
188 byte[] giveImBinaryBucket = new byte[17];
189 byte[] itemIdBytes = itemId.GetBytes();
190 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
191
192 GridInstantMessage giveIm
193 = new GridInstantMessage(
194 m_scene,
195 giverSp.UUID,
196 giverSp.Name,
197 receiverSp.UUID,
198 (byte)InstantMessageDialog.InventoryOffered,
199 false,
200 "inventory offered msg",
201 initialSessionId,
202 false,
203 Vector3.Zero,
204 giveImBinaryBucket,
205 true);
206
207 giverClient.HandleImprovedInstantMessage(giveIm);
208
209 // These details might not all be correct.
210 // Session ID is now the created item ID (!)
211 GridInstantMessage rejectIm
212 = new GridInstantMessage(
213 m_scene,
214 receiverSp.UUID,
215 receiverSp.Name,
216 giverSp.UUID,
217 (byte)InstantMessageDialog.InventoryDeclined,
218 false,
219 "inventory declined msg",
220 new UUID(receivedIm.imSessionID),
221 false,
222 Vector3.Zero,
223 null,
224 true);
225
226 receiverClient.HandleImprovedInstantMessage(rejectIm);
227
228 // Test for item remaining in the giver's inventory (here we assume a copy item)
229 // TODO: Test no-copy items.
230 InventoryItemBase originalItemAfterGive
231 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
232
233 Assert.That(originalItemAfterGive, Is.Not.Null);
234 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
235
236 // Test for item successfully making it into the receiver's inventory
237 InventoryItemBase receivedItem
238 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
239
240 InventoryFolderBase trashFolder
241 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
242
243 Assert.That(receivedItem, Is.Not.Null);
244 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
245 Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID));
246
247 // Test that on a delete, item still exists and is accessible for the giver.
248 m_scene.InventoryService.PurgeFolder(trashFolder);
249
250 InventoryItemBase originalItemAfterDelete
251 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
252
253 Assert.That(originalItemAfterDelete, Is.Not.Null);
254 }
255
256 [Test]
257 public void TestAcceptGivenFolder()
258 {
259 TestHelpers.InMethod();
260// TestHelpers.EnableLogging();
261
262 UUID initialSessionId = TestHelpers.ParseTail(0x10);
263 UUID folderId = TestHelpers.ParseTail(0x100);
264
265 UserAccount ua1
266 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
267 UserAccount ua2
268 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
269
270 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
271 TestClient giverClient = (TestClient)giverSp.ControllingClient;
272
273 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
274 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
275
276 InventoryFolderBase originalFolder
277 = UserInventoryHelpers.CreateInventoryFolder(
278 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
279
280 byte[] giveImBinaryBucket = new byte[17];
281 giveImBinaryBucket[0] = (byte)AssetType.Folder;
282 byte[] itemIdBytes = folderId.GetBytes();
283 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
284
285 GridInstantMessage giveIm
286 = new GridInstantMessage(
287 m_scene,
288 giverSp.UUID,
289 giverSp.Name,
290 receiverSp.UUID,
291 (byte)InstantMessageDialog.InventoryOffered,
292 false,
293 "inventory offered msg",
294 initialSessionId,
295 false,
296 Vector3.Zero,
297 giveImBinaryBucket,
298 true);
299
300 giverClient.HandleImprovedInstantMessage(giveIm);
301
302 // These details might not all be correct.
303 GridInstantMessage acceptIm
304 = new GridInstantMessage(
305 m_scene,
306 receiverSp.UUID,
307 receiverSp.Name,
308 giverSp.UUID,
309 (byte)InstantMessageDialog.InventoryAccepted,
310 false,
311 "inventory accepted msg",
312 initialSessionId,
313 false,
314 Vector3.Zero,
315 null,
316 true);
317
318 receiverClient.HandleImprovedInstantMessage(acceptIm);
319
320 // Test for item remaining in the giver's inventory (here we assume a copy item)
321 // TODO: Test no-copy items.
322 InventoryFolderBase originalFolderAfterGive
323 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
324
325 Assert.That(originalFolderAfterGive, Is.Not.Null);
326 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
327
328 // Test for item successfully making it into the receiver's inventory
329 InventoryFolderBase receivedFolder
330 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
331
332 Assert.That(receivedFolder, Is.Not.Null);
333 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
334
335 // Test that on a delete, item still exists and is accessible for the giver.
336 m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List<UUID>() { receivedFolder.ID });
337
338 InventoryFolderBase originalFolderAfterDelete
339 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
340
341 Assert.That(originalFolderAfterDelete, Is.Not.Null);
342
343 // TODO: Test scenario where giver deletes their item first.
344 }
345
346 /// <summary>
347 /// Test user rejection of a given item.
348 /// </summary>
349 /// <remarks>
350 /// A rejected item still ends up in the user's trash folder.
351 /// </remarks>
352 [Test]
353 public void TestRejectGivenFolder()
354 {
355 TestHelpers.InMethod();
356// TestHelpers.EnableLogging();
357
358 UUID initialSessionId = TestHelpers.ParseTail(0x10);
359 UUID folderId = TestHelpers.ParseTail(0x100);
360
361 UserAccount ua1
362 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
363 UserAccount ua2
364 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
365
366 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
367 TestClient giverClient = (TestClient)giverSp.ControllingClient;
368
369 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
370 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
371
372 // Create the folder to test give
373 InventoryFolderBase originalFolder
374 = UserInventoryHelpers.CreateInventoryFolder(
375 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
376
377 GridInstantMessage receivedIm = null;
378 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
379
380 byte[] giveImBinaryBucket = new byte[17];
381 giveImBinaryBucket[0] = (byte)AssetType.Folder;
382 byte[] itemIdBytes = folderId.GetBytes();
383 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
384
385 GridInstantMessage giveIm
386 = new GridInstantMessage(
387 m_scene,
388 giverSp.UUID,
389 giverSp.Name,
390 receiverSp.UUID,
391 (byte)InstantMessageDialog.InventoryOffered,
392 false,
393 "inventory offered msg",
394 initialSessionId,
395 false,
396 Vector3.Zero,
397 giveImBinaryBucket,
398 true);
399
400 giverClient.HandleImprovedInstantMessage(giveIm);
401
402 // These details might not all be correct.
403 // Session ID is now the created item ID (!)
404 GridInstantMessage rejectIm
405 = new GridInstantMessage(
406 m_scene,
407 receiverSp.UUID,
408 receiverSp.Name,
409 giverSp.UUID,
410 (byte)InstantMessageDialog.InventoryDeclined,
411 false,
412 "inventory declined msg",
413 new UUID(receivedIm.imSessionID),
414 false,
415 Vector3.Zero,
416 null,
417 true);
418
419 receiverClient.HandleImprovedInstantMessage(rejectIm);
420
421 // Test for item remaining in the giver's inventory (here we assume a copy item)
422 // TODO: Test no-copy items.
423 InventoryFolderBase originalFolderAfterGive
424 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
425
426 Assert.That(originalFolderAfterGive, Is.Not.Null);
427 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
428
429 // Test for folder successfully making it into the receiver's inventory
430 InventoryFolderBase receivedFolder
431 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
432
433 InventoryFolderBase trashFolder
434 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
435
436 Assert.That(receivedFolder, Is.Not.Null);
437 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
438 Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID));
439
440 // Test that on a delete, item still exists and is accessible for the giver.
441 m_scene.InventoryService.PurgeFolder(trashFolder);
442
443 InventoryFolderBase originalFolderAfterDelete
444 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
445
446 Assert.That(originalFolderAfterDelete, Is.Not.Null);
447 }
448 }
449} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 0c64f19..c517a30 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)presence.AbsolutePosition.Z + 2); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m; 170 GridInstantMessage m;
171 171
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index bf24030..2bb24ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -57,6 +57,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
57 57
58 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
59 { 59 {
60 if(config.Configs["UserProfiles"] != null)
61 return;
62
60 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); 63 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
61 m_Enabled = true; 64 m_Enabled = true;
62 } 65 }
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000..d359ebc
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1343 @@
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.IO;
30using System.Text;
31using System.Collections;
32using System.Collections.Generic;
33using System.Globalization;
34using System.Net;
35using System.Net.Sockets;
36using System.Reflection;
37using System.Xml;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using log4net;
41using Nini.Config;
42using Nwc.XmlRpc;
43using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Mono.Addins;
48using OpenSim.Services.Connectors.Hypergrid;
49
50namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
53 public class UserProfileModule : IProfileModule, INonSharedRegionModule
54 {
55 /// <summary>
56 /// Logging
57 /// </summary>
58 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 // The pair of Dictionaries are used to handle the switching of classified ads
61 // by maintaining a cache of classified id to creator id mappings and an interest
62 // count. The entries are removed when the interest count reaches 0.
63 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>();
64 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>();
65
66 public Scene Scene
67 {
68 get; private set;
69 }
70
71 /// <summary>
72 /// Gets or sets the ConfigSource.
73 /// </summary>
74 /// <value>
75 /// The configuration
76 /// </value>
77 public IConfigSource Config {
78 get;
79 set;
80 }
81
82 /// <summary>
83 /// Gets or sets the URI to the profile server.
84 /// </summary>
85 /// <value>
86 /// The profile server URI.
87 /// </value>
88 public string ProfileServerUri {
89 get;
90 set;
91 }
92
93 IProfileModule ProfileModule
94 {
95 get; set;
96 }
97
98 IUserManagement UserManagementModule
99 {
100 get; set;
101 }
102
103 /// <summary>
104 /// Gets or sets a value indicating whether this
105 /// <see cref="OpenSim.Region.Coremodules.UserProfiles.UserProfileModule"/> is enabled.
106 /// </summary>
107 /// <value>
108 /// <c>true</c> if enabled; otherwise, <c>false</c>.
109 /// </value>
110 public bool Enabled {
111 get;
112 set;
113 }
114
115 #region IRegionModuleBase implementation
116 /// <summary>
117 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
118 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
119 /// the instace for the region has been created.
120 /// </summary>
121 /// <param name='source'>
122 /// Source.
123 /// </param>
124 public void Initialise(IConfigSource source)
125 {
126 Config = source;
127 ReplaceableInterface = typeof(IProfileModule);
128
129 IConfig profileConfig = Config.Configs["UserProfiles"];
130
131 if (profileConfig == null)
132 {
133 m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration");
134 Enabled = false;
135 return;
136 }
137
138 // If we find ProfileURL then we configure for FULL support
139 // else we setup for BASIC support
140 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", "");
141 if (ProfileServerUri == "")
142 {
143 Enabled = false;
144 return;
145 }
146
147 m_log.Debug("[PROFILES]: Full Profiles Enabled");
148 ReplaceableInterface = null;
149 Enabled = true;
150 }
151
152 /// <summary>
153 /// Adds the region.
154 /// </summary>
155 /// <param name='scene'>
156 /// Scene.
157 /// </param>
158 public void AddRegion(Scene scene)
159 {
160 if(!Enabled)
161 return;
162
163 Scene = scene;
164 Scene.RegisterModuleInterface<IProfileModule>(this);
165 Scene.EventManager.OnNewClient += OnNewClient;
166 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
167
168 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
169 }
170
171 void HandleOnMakeRootAgent (ScenePresence obj)
172 {
173 if(obj.PresenceType == PresenceType.Npc)
174 return;
175
176 Util.FireAndForget(delegate
177 {
178 GetImageAssets(((IScenePresence)obj).UUID);
179 });
180 }
181
182 /// <summary>
183 /// Removes the region.
184 /// </summary>
185 /// <param name='scene'>
186 /// Scene.
187 /// </param>
188 public void RemoveRegion(Scene scene)
189 {
190 if(!Enabled)
191 return;
192 }
193
194 /// <summary>
195 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
196 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
197 /// has been called in all modules for that scene, providing an opportunity to request another module's
198 /// interface, or hook an event from another module.
199 /// </summary>
200 /// <param name='scene'>
201 /// Scene.
202 /// </param>
203 public void RegionLoaded(Scene scene)
204 {
205 if(!Enabled)
206 return;
207 }
208
209 /// <summary>
210 /// If this returns non-null, it is the type of an interface that this module intends to register. This will
211 /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
212 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
213 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
214 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
215 /// provided modules.
216 /// </summary>
217 /// <value>
218 /// The replaceable interface.
219 /// </value>
220 public Type ReplaceableInterface
221 {
222 get; private set;
223 }
224
225 /// <summary>
226 /// Called as the instance is closed.
227 /// </summary>
228 public void Close()
229 {
230 }
231
232 /// <value>
233 /// The name of the module
234 /// </value>
235 /// <summary>
236 /// Gets the module name.
237 /// </summary>
238 public string Name
239 {
240 get { return "UserProfileModule"; }
241 }
242 #endregion IRegionModuleBase implementation
243
244 #region Region Event Handlers
245 /// <summary>
246 /// Raises the new client event.
247 /// </summary>
248 /// <param name='client'>
249 /// Client.
250 /// </param>
251 void OnNewClient(IClientAPI client)
252 {
253 //Profile
254 client.OnRequestAvatarProperties += RequestAvatarProperties;
255 client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
256 client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
257
258 // Classifieds
259 client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
260 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
261 client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
262 client.OnClassifiedDelete += ClassifiedDelete;
263
264 // Picks
265 client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
266 client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
267 client.OnPickInfoUpdate += PickInfoUpdate;
268 client.OnPickDelete += PickDelete;
269
270 // Notes
271 client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
272 client.OnAvatarNotesUpdate += NotesUpdate;
273 }
274 #endregion Region Event Handlers
275
276 #region Classified
277 ///
278 /// <summary>
279 /// Handles the avatar classifieds request.
280 /// </summary>
281 /// <param name='sender'>
282 /// Sender.
283 /// </param>
284 /// <param name='method'>
285 /// Method.
286 /// </param>
287 /// <param name='args'>
288 /// Arguments.
289 /// </param>
290 public void ClassifiedsRequest(Object sender, string method, List<String> args)
291 {
292 if (!(sender is IClientAPI))
293 return;
294
295 IClientAPI remoteClient = (IClientAPI)sender;
296
297 UUID targetID;
298 UUID.TryParse(args[0], out targetID);
299
300 // Can't handle NPC yet...
301 ScenePresence p = FindPresence(targetID);
302
303 if (null != p)
304 {
305 if (p.PresenceType == PresenceType.Npc)
306 return;
307 }
308
309 string serverURI = string.Empty;
310 GetUserProfileServerURI(targetID, out serverURI);
311 UUID creatorId = UUID.Zero;
312 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
313
314 OSDMap parameters= new OSDMap();
315 UUID.TryParse(args[0], out creatorId);
316 parameters.Add("creatorId", OSD.FromUUID(creatorId));
317 OSD Params = (OSD)parameters;
318 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
319 {
320 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
321 return;
322 }
323
324 parameters = (OSDMap)Params;
325
326 OSDArray list = (OSDArray)parameters["result"];
327
328
329 foreach(OSD map in list)
330 {
331 OSDMap m = (OSDMap)map;
332 UUID cid = m["classifieduuid"].AsUUID();
333 string name = m["name"].AsString();
334
335 classifieds[cid] = name;
336
337 lock (m_classifiedCache)
338 {
339 if (!m_classifiedCache.ContainsKey(cid))
340 {
341 m_classifiedCache.Add(cid,creatorId);
342 m_classifiedInterest.Add(cid, 0);
343 }
344
345 m_classifiedInterest[cid]++;
346 }
347 }
348
349 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
350 }
351
352 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
353 {
354 UUID target = remoteClient.AgentId;
355 UserClassifiedAdd ad = new UserClassifiedAdd();
356 ad.ClassifiedId = queryClassifiedID;
357
358 lock (m_classifiedCache)
359 {
360 if (m_classifiedCache.ContainsKey(queryClassifiedID))
361 {
362 target = m_classifiedCache[queryClassifiedID];
363
364 m_classifiedInterest[queryClassifiedID] --;
365
366 if (m_classifiedInterest[queryClassifiedID] == 0)
367 {
368 m_classifiedInterest.Remove(queryClassifiedID);
369 m_classifiedCache.Remove(queryClassifiedID);
370 }
371 }
372 }
373
374 string serverURI = string.Empty;
375 GetUserProfileServerURI(target, out serverURI);
376
377 object Ad = (object)ad;
378 if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
379 {
380 remoteClient.SendAgentAlertMessage(
381 "Error getting classified info", false);
382 return;
383 }
384 ad = (UserClassifiedAdd) Ad;
385
386 if(ad.CreatorId == UUID.Zero)
387 return;
388
389 Vector3 globalPos = new Vector3();
390 Vector3.TryParse(ad.GlobalPos, out globalPos);
391
392 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
393 (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
394 ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
395
396 }
397
398 /// <summary>
399 /// Classifieds info update.
400 /// </summary>
401 /// <param name='queryclassifiedID'>
402 /// Queryclassified I.
403 /// </param>
404 /// <param name='queryCategory'>
405 /// Query category.
406 /// </param>
407 /// <param name='queryName'>
408 /// Query name.
409 /// </param>
410 /// <param name='queryDescription'>
411 /// Query description.
412 /// </param>
413 /// <param name='queryParcelID'>
414 /// Query parcel I.
415 /// </param>
416 /// <param name='queryParentEstate'>
417 /// Query parent estate.
418 /// </param>
419 /// <param name='querySnapshotID'>
420 /// Query snapshot I.
421 /// </param>
422 /// <param name='queryGlobalPos'>
423 /// Query global position.
424 /// </param>
425 /// <param name='queryclassifiedFlags'>
426 /// Queryclassified flags.
427 /// </param>
428 /// <param name='queryclassifiedPrice'>
429 /// Queryclassified price.
430 /// </param>
431 /// <param name='remoteClient'>
432 /// Remote client.
433 /// </param>
434 public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
435 uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
436 int queryclassifiedPrice, IClientAPI remoteClient)
437 {
438 UserClassifiedAdd ad = new UserClassifiedAdd();
439
440 Scene s = (Scene) remoteClient.Scene;
441 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
442 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
443 ScenePresence p = FindPresence(remoteClient.AgentId);
444
445 string serverURI = string.Empty;
446 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
447
448 if (land == null)
449 {
450 ad.ParcelName = string.Empty;
451 }
452 else
453 {
454 ad.ParcelName = land.LandData.Name;
455 }
456
457 ad.CreatorId = remoteClient.AgentId;
458 ad.ClassifiedId = queryclassifiedID;
459 ad.Category = Convert.ToInt32(queryCategory);
460 ad.Name = queryName;
461 ad.Description = queryDescription;
462 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
463 ad.SnapshotId = querySnapshotID;
464 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
465 ad.GlobalPos = queryGlobalPos.ToString ();
466 ad.Flags = queryclassifiedFlags;
467 ad.Price = queryclassifiedPrice;
468 ad.ParcelId = p.currentParcelUUID;
469
470 object Ad = ad;
471
472 OSD.SerializeMembers(Ad);
473
474 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
475 {
476 remoteClient.SendAgentAlertMessage(
477 "Error updating classified", false);
478 }
479 }
480
481 /// <summary>
482 /// Classifieds delete.
483 /// </summary>
484 /// <param name='queryClassifiedID'>
485 /// Query classified I.
486 /// </param>
487 /// <param name='remoteClient'>
488 /// Remote client.
489 /// </param>
490 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
491 {
492 string serverURI = string.Empty;
493 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
494
495 UUID classifiedId;
496 OSDMap parameters= new OSDMap();
497 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
498 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
499 OSD Params = (OSD)parameters;
500 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
501 {
502 remoteClient.SendAgentAlertMessage(
503 "Error classified delete", false);
504 }
505
506 parameters = (OSDMap)Params;
507 }
508 #endregion Classified
509
510 #region Picks
511 /// <summary>
512 /// Handles the avatar picks request.
513 /// </summary>
514 /// <param name='sender'>
515 /// Sender.
516 /// </param>
517 /// <param name='method'>
518 /// Method.
519 /// </param>
520 /// <param name='args'>
521 /// Arguments.
522 /// </param>
523 public void PicksRequest(Object sender, string method, List<String> args)
524 {
525 if (!(sender is IClientAPI))
526 return;
527
528 IClientAPI remoteClient = (IClientAPI)sender;
529
530 UUID targetId;
531 UUID.TryParse(args[0], out targetId);
532
533 // Can't handle NPC yet...
534 ScenePresence p = FindPresence(targetId);
535
536 if (null != p)
537 {
538 if (p.PresenceType == PresenceType.Npc)
539 return;
540 }
541
542 string serverURI = string.Empty;
543 GetUserProfileServerURI(targetId, out serverURI);
544
545 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
546
547 OSDMap parameters= new OSDMap();
548 parameters.Add("creatorId", OSD.FromUUID(targetId));
549 OSD Params = (OSD)parameters;
550 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
551 {
552 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
553 return;
554 }
555
556 parameters = (OSDMap)Params;
557
558 OSDArray list = (OSDArray)parameters["result"];
559
560 foreach(OSD map in list)
561 {
562 OSDMap m = (OSDMap)map;
563 UUID cid = m["pickuuid"].AsUUID();
564 string name = m["name"].AsString();
565
566 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
567
568 picks[cid] = name;
569 }
570 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
571 }
572
573 /// <summary>
574 /// Handles the pick info request.
575 /// </summary>
576 /// <param name='sender'>
577 /// Sender.
578 /// </param>
579 /// <param name='method'>
580 /// Method.
581 /// </param>
582 /// <param name='args'>
583 /// Arguments.
584 /// </param>
585 public void PickInfoRequest(Object sender, string method, List<String> args)
586 {
587 if (!(sender is IClientAPI))
588 return;
589
590 UUID targetID;
591 UUID.TryParse(args[0], out targetID);
592 string serverURI = string.Empty;
593 GetUserProfileServerURI(targetID, out serverURI);
594 IClientAPI remoteClient = (IClientAPI)sender;
595
596 UserProfilePick pick = new UserProfilePick();
597 UUID.TryParse(args[0], out pick.CreatorId);
598 UUID.TryParse(args[1], out pick.PickId);
599
600
601 object Pick = (object)pick;
602 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
603 {
604 remoteClient.SendAgentAlertMessage(
605 "Error selecting pick", false);
606 }
607 pick = (UserProfilePick) Pick;
608 if(pick.SnapshotId == UUID.Zero)
609 {
610 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
611 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
612 return;
613 }
614
615 Vector3 globalPos;
616 Vector3.TryParse(pick.GlobalPos,out globalPos);
617
618 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
619
620 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
621 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
622 globalPos,pick.SortOrder,pick.Enabled);
623 }
624
625 /// <summary>
626 /// Updates the userpicks
627 /// </summary>
628 /// <param name='remoteClient'>
629 /// Remote client.
630 /// </param>
631 /// <param name='pickID'>
632 /// Pick I.
633 /// </param>
634 /// <param name='creatorID'>
635 /// the creator of the pick
636 /// </param>
637 /// <param name='topPick'>
638 /// Top pick.
639 /// </param>
640 /// <param name='name'>
641 /// Name.
642 /// </param>
643 /// <param name='desc'>
644 /// Desc.
645 /// </param>
646 /// <param name='snapshotID'>
647 /// Snapshot I.
648 /// </param>
649 /// <param name='sortOrder'>
650 /// Sort order.
651 /// </param>
652 /// <param name='enabled'>
653 /// Enabled.
654 /// </param>
655 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
656 {
657
658 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
659 UserProfilePick pick = new UserProfilePick();
660 string serverURI = string.Empty;
661 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
662 ScenePresence p = FindPresence(remoteClient.AgentId);
663
664 Vector3 avaPos = p.AbsolutePosition;
665 // Getting the global position for the Avatar
666 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
667 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
668 avaPos.Z);
669
670 string landOwnerName = string.Empty;
671 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
672 if(land.LandData.IsGroupOwned)
673 {
674 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
675 UUID groupId = land.LandData.GroupID;
676 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
677 landOwnerName = groupRecord.GroupName;
678 }
679 else
680 {
681 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
682 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
683 landOwnerName = user.Name;
684 }
685
686 pick.PickId = pickID;
687 pick.CreatorId = creatorID;
688 pick.TopPick = topPick;
689 pick.Name = name;
690 pick.Desc = desc;
691 pick.ParcelId = p.currentParcelUUID;
692 pick.SnapshotId = snapshotID;
693 pick.User = landOwnerName;
694 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
695 pick.GlobalPos = posGlobal.ToString();
696 pick.SortOrder = sortOrder;
697 pick.Enabled = enabled;
698
699 object Pick = (object)pick;
700 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
701 {
702 remoteClient.SendAgentAlertMessage(
703 "Error updating pick", false);
704 }
705
706 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
707 }
708
709 /// <summary>
710 /// Delete a Pick
711 /// </summary>
712 /// <param name='remoteClient'>
713 /// Remote client.
714 /// </param>
715 /// <param name='queryPickID'>
716 /// Query pick I.
717 /// </param>
718 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
719 {
720 string serverURI = string.Empty;
721 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
722
723 OSDMap parameters= new OSDMap();
724 parameters.Add("pickId", OSD.FromUUID(queryPickID));
725 OSD Params = (OSD)parameters;
726 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
727 {
728 remoteClient.SendAgentAlertMessage(
729 "Error picks delete", false);
730 }
731 }
732 #endregion Picks
733
734 #region Notes
735 /// <summary>
736 /// Handles the avatar notes request.
737 /// </summary>
738 /// <param name='sender'>
739 /// Sender.
740 /// </param>
741 /// <param name='method'>
742 /// Method.
743 /// </param>
744 /// <param name='args'>
745 /// Arguments.
746 /// </param>
747 public void NotesRequest(Object sender, string method, List<String> args)
748 {
749 UserProfileNotes note = new UserProfileNotes();
750
751 if (!(sender is IClientAPI))
752 return;
753
754 IClientAPI remoteClient = (IClientAPI)sender;
755 string serverURI = string.Empty;
756 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
757 note.UserId = remoteClient.AgentId;
758 UUID.TryParse(args[0], out note.TargetId);
759
760 object Note = (object)note;
761 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
762 {
763 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
764 return;
765 }
766 note = (UserProfileNotes) Note;
767
768 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
769 }
770
771 /// <summary>
772 /// Avatars the notes update.
773 /// </summary>
774 /// <param name='remoteClient'>
775 /// Remote client.
776 /// </param>
777 /// <param name='queryTargetID'>
778 /// Query target I.
779 /// </param>
780 /// <param name='queryNotes'>
781 /// Query notes.
782 /// </param>
783 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
784 {
785 UserProfileNotes note = new UserProfileNotes();
786
787 note.UserId = remoteClient.AgentId;
788 note.TargetId = queryTargetID;
789 note.Notes = queryNotes;
790
791 string serverURI = string.Empty;
792 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
793
794 object Note = note;
795 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
796 {
797 return;
798 }
799 }
800 #endregion Notes
801
802 #region Avatar Properties
803 /// <summary>
804 /// Update the avatars interests .
805 /// </summary>
806 /// <param name='remoteClient'>
807 /// Remote client.
808 /// </param>
809 /// <param name='wantmask'>
810 /// Wantmask.
811 /// </param>
812 /// <param name='wanttext'>
813 /// Wanttext.
814 /// </param>
815 /// <param name='skillsmask'>
816 /// Skillsmask.
817 /// </param>
818 /// <param name='skillstext'>
819 /// Skillstext.
820 /// </param>
821 /// <param name='languages'>
822 /// Languages.
823 /// </param>
824 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
825 {
826 UserProfileProperties prop = new UserProfileProperties();
827
828 prop.UserId = remoteClient.AgentId;
829 prop.WantToMask = (int)wantmask;
830 prop.WantToText = wanttext;
831 prop.SkillsMask = (int)skillsmask;
832 prop.SkillsText = skillstext;
833 prop.Language = languages;
834
835 string serverURI = string.Empty;
836 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
837
838 object Param = prop;
839 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
840 {
841 remoteClient.SendAgentAlertMessage(
842 "Error updating interests", false);
843 }
844 }
845
846 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
847 {
848 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
849 {
850 // Looking for a reason that some viewers are sending null Id's
851 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
852 return;
853 }
854
855 // Can't handle NPC yet...
856 ScenePresence p = FindPresence(avatarID);
857
858 if (null != p)
859 {
860 if (p.PresenceType == PresenceType.Npc)
861 return;
862 }
863
864 string serverURI = string.Empty;
865 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
866
867 UserAccount account = null;
868 Dictionary<string,object> userInfo;
869
870 if (!foreign)
871 {
872 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
873 }
874 else
875 {
876 userInfo = new Dictionary<string, object>();
877 }
878
879 Byte[] charterMember = new Byte[1];
880 string born = String.Empty;
881 uint flags = 0x00;
882
883 if (null != account)
884 {
885 if (account.UserTitle == "")
886 {
887 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
888 }
889 else
890 {
891 charterMember = Utils.StringToBytes(account.UserTitle);
892 }
893
894 born = Util.ToDateTime(account.Created).ToString(
895 "M/d/yyyy", CultureInfo.InvariantCulture);
896 flags = (uint)(account.UserFlags & 0xff);
897 }
898 else
899 {
900 if (GetUserAccountData(avatarID, out userInfo) == true)
901 {
902 if ((string)userInfo["user_title"] == "")
903 {
904 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
905 }
906 else
907 {
908 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
909 }
910
911 int val_born = (int)userInfo["user_created"];
912 born = Util.ToDateTime(val_born).ToString(
913 "M/d/yyyy", CultureInfo.InvariantCulture);
914
915 // picky, picky
916 int val_flags = (int)userInfo["user_flags"];
917 flags = (uint)(val_flags & 0xff);
918 }
919 }
920
921 UserProfileProperties props = new UserProfileProperties();
922 string result = string.Empty;
923
924 props.UserId = avatarID;
925 GetProfileData(ref props, out result);
926
927 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
928 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
929
930
931 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
932 props.SkillsText, props.Language);
933 }
934
935 /// <summary>
936 /// Updates the avatar properties.
937 /// </summary>
938 /// <param name='remoteClient'>
939 /// Remote client.
940 /// </param>
941 /// <param name='newProfile'>
942 /// New profile.
943 /// </param>
944 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
945 {
946 if (remoteClient.AgentId == newProfile.ID)
947 {
948 UserProfileProperties prop = new UserProfileProperties();
949
950 prop.UserId = remoteClient.AgentId;
951 prop.WebUrl = newProfile.ProfileUrl;
952 prop.ImageId = newProfile.Image;
953 prop.AboutText = newProfile.AboutText;
954 prop.FirstLifeImageId = newProfile.FirstLifeImage;
955 prop.FirstLifeText = newProfile.FirstLifeAboutText;
956
957 string serverURI = string.Empty;
958 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
959
960 object Prop = prop;
961
962 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
963 {
964 remoteClient.SendAgentAlertMessage(
965 "Error updating properties", false);
966 }
967
968 RequestAvatarProperties(remoteClient, newProfile.ID);
969 }
970 }
971
972 /// <summary>
973 /// Gets the profile data.
974 /// </summary>
975 /// <returns>
976 /// The profile data.
977 /// </returns>
978 /// <param name='userID'>
979 /// User I.
980 /// </param>
981 bool GetProfileData(ref UserProfileProperties properties, out string message)
982 {
983 // Can't handle NPC yet...
984 ScenePresence p = FindPresence(properties.UserId);
985
986 if (null != p)
987 {
988 if (p.PresenceType == PresenceType.Npc)
989 {
990 message = "Id points to NPC";
991 return false;
992 }
993 }
994
995 string serverURI = string.Empty;
996 GetUserProfileServerURI(properties.UserId, out serverURI);
997
998 // This is checking a friend on the home grid
999 // Not HG friend
1000 if ( String.IsNullOrEmpty(serverURI))
1001 {
1002 message = "No Presence - foreign friend";
1003 return false;
1004 }
1005
1006 object Prop = (object)properties;
1007 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1008 properties = (UserProfileProperties)Prop;
1009
1010 message = "Success";
1011 return true;
1012 }
1013 #endregion Avatar Properties
1014
1015 #region Utils
1016 bool GetImageAssets(UUID avatarId)
1017 {
1018 string profileServerURI = string.Empty;
1019 string assetServerURI = string.Empty;
1020
1021 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1022
1023 if(!foreign)
1024 return true;
1025
1026 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1027
1028 OSDMap parameters= new OSDMap();
1029 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1030 OSD Params = (OSD)parameters;
1031 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1032 {
1033 return false;
1034 }
1035
1036 parameters = (OSDMap)Params;
1037
1038 OSDArray list = (OSDArray)parameters["result"];
1039
1040 foreach(OSD asset in list)
1041 {
1042 OSDString assetId = (OSDString)asset;
1043
1044 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()));
1045 }
1046 return true;
1047 }
1048
1049 /// <summary>
1050 /// Gets the user account data.
1051 /// </summary>
1052 /// <returns>
1053 /// The user profile data.
1054 /// </returns>
1055 /// <param name='userID'>
1056 /// If set to <c>true</c> user I.
1057 /// </param>
1058 /// <param name='userInfo'>
1059 /// If set to <c>true</c> user info.
1060 /// </param>
1061 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1062 {
1063 Dictionary<string,object> info = new Dictionary<string, object>();
1064
1065 if (UserManagementModule.IsLocalGridUser(userID))
1066 {
1067 // Is local
1068 IUserAccountService uas = Scene.UserAccountService;
1069 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1070
1071 info["user_flags"] = account.UserFlags;
1072 info["user_created"] = account.Created;
1073
1074 if (!String.IsNullOrEmpty(account.UserTitle))
1075 info["user_title"] = account.UserTitle;
1076 else
1077 info["user_title"] = "";
1078
1079 userInfo = info;
1080
1081 return false;
1082 }
1083 else
1084 {
1085 // Is Foreign
1086 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1087
1088 if (String.IsNullOrEmpty(home_url))
1089 {
1090 info["user_flags"] = 0;
1091 info["user_created"] = 0;
1092 info["user_title"] = "Unavailable";
1093
1094 userInfo = info;
1095 return true;
1096 }
1097
1098 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1099
1100 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1101
1102 if (account.Count > 0)
1103 {
1104 if (account.ContainsKey("user_flags"))
1105 info["user_flags"] = account["user_flags"];
1106 else
1107 info["user_flags"] = "";
1108
1109 if (account.ContainsKey("user_created"))
1110 info["user_created"] = account["user_created"];
1111 else
1112 info["user_created"] = "";
1113
1114 info["user_title"] = "HG Visitor";
1115 }
1116 else
1117 {
1118 info["user_flags"] = 0;
1119 info["user_created"] = 0;
1120 info["user_title"] = "HG Visitor";
1121 }
1122 userInfo = info;
1123 return true;
1124 }
1125 }
1126
1127 /// <summary>
1128 /// Gets the user profile server UR.
1129 /// </summary>
1130 /// <returns>
1131 /// The user profile server UR.
1132 /// </returns>
1133 /// <param name='userID'>
1134 /// If set to <c>true</c> user I.
1135 /// </param>
1136 /// <param name='serverURI'>
1137 /// If set to <c>true</c> server UR.
1138 /// </param>
1139 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1140 {
1141 bool local;
1142 local = UserManagementModule.IsLocalGridUser(userID);
1143
1144 if (!local)
1145 {
1146 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1147 // Is Foreign
1148 return true;
1149 }
1150 else
1151 {
1152 serverURI = ProfileServerUri;
1153 // Is local
1154 return false;
1155 }
1156 }
1157
1158 /// <summary>
1159 /// Finds the presence.
1160 /// </summary>
1161 /// <returns>
1162 /// The presence.
1163 /// </returns>
1164 /// <param name='clientID'>
1165 /// Client I.
1166 /// </param>
1167 ScenePresence FindPresence(UUID clientID)
1168 {
1169 ScenePresence p;
1170
1171 p = Scene.GetScenePresence(clientID);
1172 if (p != null && !p.IsChildAgent)
1173 return p;
1174
1175 return null;
1176 }
1177 #endregion Util
1178
1179 #region Web Util
1180 /// <summary>
1181 /// Sends json-rpc request with a serializable type.
1182 /// </summary>
1183 /// <returns>
1184 /// OSD Map.
1185 /// </returns>
1186 /// <param name='parameters'>
1187 /// Serializable type .
1188 /// </param>
1189 /// <param name='method'>
1190 /// Json-rpc method to call.
1191 /// </param>
1192 /// <param name='uri'>
1193 /// URI of json-rpc service.
1194 /// </param>
1195 /// <param name='jsonId'>
1196 /// Id for our call.
1197 /// </param>
1198 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1199 {
1200 if (jsonId == null)
1201 throw new ArgumentNullException ("jsonId");
1202 if (uri == null)
1203 throw new ArgumentNullException ("uri");
1204 if (method == null)
1205 throw new ArgumentNullException ("method");
1206 if (parameters == null)
1207 throw new ArgumentNullException ("parameters");
1208
1209 // Prep our payload
1210 OSDMap json = new OSDMap();
1211
1212 json.Add("jsonrpc", OSD.FromString("2.0"));
1213 json.Add("id", OSD.FromString(jsonId));
1214 json.Add("method", OSD.FromString(method));
1215
1216 json.Add("params", OSD.SerializeMembers(parameters));
1217
1218 string jsonRequestData = OSDParser.SerializeJsonString(json);
1219 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1220
1221 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1222
1223 webRequest.ContentType = "application/json-rpc";
1224 webRequest.Method = "POST";
1225
1226 Stream dataStream = webRequest.GetRequestStream();
1227 dataStream.Write(content, 0, content.Length);
1228 dataStream.Close();
1229
1230 WebResponse webResponse = null;
1231 try
1232 {
1233 webResponse = webRequest.GetResponse();
1234 }
1235 catch (WebException e)
1236 {
1237 Console.WriteLine("Web Error" + e.Message);
1238 Console.WriteLine ("Please check input");
1239 return false;
1240 }
1241
1242 Stream rstream = webResponse.GetResponseStream();
1243
1244 OSDMap mret = new OSDMap();
1245 try
1246 {
1247 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1248 }
1249 catch (Exception e)
1250 {
1251 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1252 return false;
1253 }
1254
1255
1256 if (mret.ContainsKey("error"))
1257 return false;
1258
1259 // get params...
1260 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1261 return true;
1262 }
1263
1264 /// <summary>
1265 /// Sends json-rpc request with OSD parameter.
1266 /// </summary>
1267 /// <returns>
1268 /// The rpc request.
1269 /// </returns>
1270 /// <param name='data'>
1271 /// data - incoming as parameters, outgong as result/error
1272 /// </param>
1273 /// <param name='method'>
1274 /// Json-rpc method to call.
1275 /// </param>
1276 /// <param name='uri'>
1277 /// URI of json-rpc service.
1278 /// </param>
1279 /// <param name='jsonId'>
1280 /// If set to <c>true</c> json identifier.
1281 /// </param>
1282 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1283 {
1284 OSDMap map = new OSDMap();
1285
1286 map["jsonrpc"] = "2.0";
1287 if(string.IsNullOrEmpty(jsonId))
1288 map["id"] = UUID.Random().ToString();
1289 else
1290 map["id"] = jsonId;
1291
1292 map["method"] = method;
1293 map["params"] = data;
1294
1295 string jsonRequestData = OSDParser.SerializeJsonString(map);
1296 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1297
1298 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1299 webRequest.ContentType = "application/json-rpc";
1300 webRequest.Method = "POST";
1301
1302 Stream dataStream = webRequest.GetRequestStream();
1303 dataStream.Write(content, 0, content.Length);
1304 dataStream.Close();
1305
1306 WebResponse webResponse = null;
1307 try
1308 {
1309 webResponse = webRequest.GetResponse();
1310 }
1311 catch (WebException e)
1312 {
1313 Console.WriteLine("Web Error" + e.Message);
1314 Console.WriteLine ("Please check input");
1315 return false;
1316 }
1317
1318 Stream rstream = webResponse.GetResponseStream();
1319
1320 OSDMap response = new OSDMap();
1321 try
1322 {
1323 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1324 }
1325 catch (Exception e)
1326 {
1327 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1328 return false;
1329 }
1330
1331 if(response.ContainsKey("error"))
1332 {
1333 data = response["error"];
1334 return false;
1335 }
1336
1337 data = response;
1338
1339 return true;
1340 }
1341 #endregion Web Util
1342 }
1343} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index fff86d5..498cc2f 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
33using log4net; 34using log4net;
@@ -37,6 +38,7 @@ using OpenMetaverse;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
39using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
42using Caps=OpenSim.Framework.Capabilities.Caps; 44using Caps=OpenSim.Framework.Capabilities.Caps;
@@ -57,8 +59,9 @@ namespace OpenSim.Region.CoreModules.Framework
57 /// </summary> 59 /// </summary>
58 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>(); 60 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
59 61
60 protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); 62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>();
61 protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds 63
64 protected Dictionary<UUID, Dictionary<ulong, string>> m_childrenSeeds
62 = new Dictionary<UUID, Dictionary<ulong, string>>(); 65 = new Dictionary<UUID, Dictionary<ulong, string>>();
63 66
64 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
@@ -70,9 +73,24 @@ namespace OpenSim.Region.CoreModules.Framework
70 m_scene = scene; 73 m_scene = scene;
71 m_scene.RegisterModuleInterface<ICapabilitiesModule>(this); 74 m_scene.RegisterModuleInterface<ICapabilitiesModule>(this);
72 75
73 MainConsole.Instance.Commands.AddCommand("Comms", false, "show caps", 76 MainConsole.Instance.Commands.AddCommand(
74 "show caps", 77 "Comms", false, "show caps list",
75 "Shows all registered capabilities for users", HandleShowCapsCommand); 78 "show caps list",
79 "Shows list of registered capabilities for users.", HandleShowCapsListCommand);
80
81 MainConsole.Instance.Commands.AddCommand(
82 "Comms", false, "show caps stats by user",
83 "show caps stats by user [<first-name> <last-name>]",
84 "Shows statistics on capabilities use by user.",
85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.",
86 HandleShowCapsStatsByUserCommand);
87
88 MainConsole.Instance.Commands.AddCommand(
89 "Comms", false, "show caps stats by cap",
90 "show caps stats by cap [<cap-name>]",
91 "Shows statistics on capabilities use by capability.",
92 "If a capability name is given, then prints a detailed breakdown of use by each user.",
93 HandleShowCapsStatsByCapCommand);
76 } 94 }
77 95
78 public void RegionLoaded(Scene scene) 96 public void RegionLoaded(Scene scene)
@@ -102,39 +120,56 @@ namespace OpenSim.Region.CoreModules.Framework
102 120
103 public void CreateCaps(UUID agentId, uint circuitCode) 121 public void CreateCaps(UUID agentId, uint circuitCode)
104 { 122 {
123// int ts = Util.EnvironmentTickCount();
124/* this as no business here...
125 * must be done elsewhere ( and is )
105 int flags = m_scene.GetUserFlags(agentId); 126 int flags = m_scene.GetUserFlags(agentId);
127
128 m_log.ErrorFormat("[CreateCaps]: banCheck {0} ", Util.EnvironmentTickCountSubtract(ts));
129
106 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) 130 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
107 return; 131 return;
108 132*/
133 Caps caps;
109 String capsObjectPath = GetCapsPath(agentId); 134 String capsObjectPath = GetCapsPath(agentId);
110 135
111 if (m_capsObjects.ContainsKey(circuitCode)) 136 lock (m_capsObjects)
112 { 137 {
113 Caps oldCaps = m_capsObjects[circuitCode]; 138 if (m_capsObjects.ContainsKey(circuitCode))
114 139 {
115 m_log.DebugFormat( 140 Caps oldCaps = m_capsObjects[circuitCode];
116 "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", 141
117 agentId, oldCaps.CapsObjectPath, capsObjectPath); 142// if (capsObjectPath == oldCaps.CapsObjectPath)
118 // This should not happen. The caller code is confused. We need to fix that. 143// {
119 // CAPs can never be reregistered, or the client will be confused. 144// m_log.WarnFormat(
120 // Hence this return here. 145// "[CAPS]: Reusing caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ",
121 //return; 146// agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath);
122 } 147// return;
148// }
149 }
123 150
124 Caps caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName, 151 caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName,
125 (MainServer.Instance == null) ? 0: MainServer.Instance.Port, 152 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
126 capsObjectPath, agentId, m_scene.RegionInfo.RegionName); 153 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
127 154
128 m_capsObjects[circuitCode] = caps; 155// m_log.ErrorFormat("[CreateCaps]: new caps {0} ", Util.EnvironmentTickCountSubtract(ts));
129 156
157 m_capsObjects[circuitCode] = caps;
158 }
130 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 159 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
160// m_log.ErrorFormat("[CreateCaps]: end {0} ", Util.EnvironmentTickCountSubtract(ts));
161
131 } 162 }
132 163
133 public void RemoveCaps(UUID agentId, uint circuitCode) 164 public void RemoveCaps(UUID agentId, uint circuitCode)
134 { 165 {
135 if (childrenSeeds.ContainsKey(agentId)) 166 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName);
167 lock (m_childrenSeeds)
136 { 168 {
137 childrenSeeds.Remove(agentId); 169 if (m_childrenSeeds.ContainsKey(agentId))
170 {
171 m_childrenSeeds.Remove(agentId);
172 }
138 } 173 }
139 174
140 lock (m_capsObjects) 175 lock (m_capsObjects)
@@ -180,16 +215,22 @@ namespace OpenSim.Region.CoreModules.Framework
180 215
181 public void SetAgentCapsSeeds(AgentCircuitData agent) 216 public void SetAgentCapsSeeds(AgentCircuitData agent)
182 { 217 {
183 capsPaths[agent.AgentID] = agent.CapsPath; 218 lock (m_capsPaths)
184 childrenSeeds[agent.AgentID] 219 m_capsPaths[agent.AgentID] = agent.CapsPath;
185 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds); 220
221 lock (m_childrenSeeds)
222 m_childrenSeeds[agent.AgentID]
223 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds);
186 } 224 }
187 225
188 public string GetCapsPath(UUID agentId) 226 public string GetCapsPath(UUID agentId)
189 { 227 {
190 if (capsPaths.ContainsKey(agentId)) 228 lock (m_capsPaths)
191 { 229 {
192 return capsPaths[agentId]; 230 if (m_capsPaths.ContainsKey(agentId))
231 {
232 return m_capsPaths[agentId];
233 }
193 } 234 }
194 235
195 return null; 236 return null;
@@ -198,17 +239,24 @@ namespace OpenSim.Region.CoreModules.Framework
198 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID) 239 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID)
199 { 240 {
200 Dictionary<ulong, string> seeds = null; 241 Dictionary<ulong, string> seeds = null;
201 if (childrenSeeds.TryGetValue(agentID, out seeds)) 242
202 return seeds; 243 lock (m_childrenSeeds)
244 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
245 return seeds;
246
203 return new Dictionary<ulong, string>(); 247 return new Dictionary<ulong, string>();
204 } 248 }
205 249
206 public void DropChildSeed(UUID agentID, ulong handle) 250 public void DropChildSeed(UUID agentID, ulong handle)
207 { 251 {
208 Dictionary<ulong, string> seeds; 252 Dictionary<ulong, string> seeds;
209 if (childrenSeeds.TryGetValue(agentID, out seeds)) 253
254 lock (m_childrenSeeds)
210 { 255 {
211 seeds.Remove(handle); 256 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
257 {
258 seeds.Remove(handle);
259 }
212 } 260 }
213 } 261 }
214 262
@@ -216,53 +264,339 @@ namespace OpenSim.Region.CoreModules.Framework
216 { 264 {
217 Dictionary<ulong, string> seeds; 265 Dictionary<ulong, string> seeds;
218 string returnval; 266 string returnval;
219 if (childrenSeeds.TryGetValue(agentID, out seeds)) 267
268 lock (m_childrenSeeds)
220 { 269 {
221 if (seeds.TryGetValue(handle, out returnval)) 270 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
222 return returnval; 271 {
272 if (seeds.TryGetValue(handle, out returnval))
273 return returnval;
274 }
223 } 275 }
276
224 return null; 277 return null;
225 } 278 }
226 279
227 public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds) 280 public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds)
228 { 281 {
229 //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count); 282 //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count);
230 childrenSeeds[agentID] = seeds; 283
284 lock (m_childrenSeeds)
285 m_childrenSeeds[agentID] = seeds;
231 } 286 }
232 287
233 public void DumpChildrenSeeds(UUID agentID) 288 public void DumpChildrenSeeds(UUID agentID)
234 { 289 {
235 m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================"); 290 m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================");
236 foreach (KeyValuePair<ulong, string> kvp in childrenSeeds[agentID]) 291
292 lock (m_childrenSeeds)
293 {
294 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
295 {
296 uint x, y;
297 Utils.LongToUInts(kvp.Key, out x, out y);
298 x = x / Constants.RegionSize;
299 y = y / Constants.RegionSize;
300 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
301 }
302 }
303 }
304
305 private void HandleShowCapsListCommand(string module, string[] cmdParams)
306 {
307 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
308 return;
309
310 StringBuilder capsReport = new StringBuilder();
311 capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
312
313 lock (m_capsObjects)
314 {
315 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
316 {
317 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
318 Caps caps = kvp.Value;
319
320 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
321 {
322 Uri uri = new Uri(kvp2.Value.ToString());
323 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
324 }
325
326 foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers())
327 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url);
328
329 foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers)
330 capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
331 }
332 }
333
334 MainConsole.Instance.Output(capsReport.ToString());
335 }
336
337 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams)
338 {
339 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
340 return;
341
342 if (cmdParams.Length != 5 && cmdParams.Length != 6)
343 {
344 MainConsole.Instance.Output("Usage: show caps stats by cap [<cap-name>]");
345 return;
346 }
347
348 StringBuilder sb = new StringBuilder();
349 sb.AppendFormat("Region {0}:\n", m_scene.Name);
350
351 if (cmdParams.Length == 5)
352 {
353 BuildSummaryStatsByCapReport(sb);
354 }
355 else if (cmdParams.Length == 6)
237 { 356 {
238 uint x, y; 357 BuildDetailedStatsByCapReport(sb, cmdParams[5]);
239 Utils.LongToUInts(kvp.Key, out x, out y);
240 x = x / Constants.RegionSize;
241 y = y / Constants.RegionSize;
242 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
243 } 358 }
359
360 MainConsole.Instance.Output(sb.ToString());
244 } 361 }
245 362
246 private void HandleShowCapsCommand(string module, string[] cmdparams) 363 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName)
247 { 364 {
248 StringBuilder caps = new StringBuilder(); 365 /*
249 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); 366 sb.AppendFormat("Capability name {0}\n", capName);
367
368 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
369 cdt.AddColumn("User Name", 34);
370 cdt.AddColumn("Req Received", 12);
371 cdt.AddColumn("Req Handled", 12);
372 cdt.Indent = 2;
373
374 Dictionary<string, int> receivedStats = new Dictionary<string, int>();
375 Dictionary<string, int> handledStats = new Dictionary<string, int>();
250 376
251 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) 377 m_scene.ForEachScenePresence(
378 sp =>
379 {
380 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
381
382 if (caps == null)
383 return;
384
385 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
386
387 IRequestHandler reqHandler;
388 if (capsHandlers.TryGetValue(capName, out reqHandler))
389 {
390 receivedStats[sp.Name] = reqHandler.RequestsReceived;
391 handledStats[sp.Name] = reqHandler.RequestsHandled;
392 }
393 else
394 {
395 PollServiceEventArgs pollHandler = null;
396 if (caps.TryGetPollHandler(capName, out pollHandler))
397 {
398 receivedStats[sp.Name] = pollHandler.RequestsReceived;
399 handledStats[sp.Name] = pollHandler.RequestsHandled;
400 }
401 }
402 }
403 );
404
405 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
252 { 406 {
253 caps.AppendFormat("** Circuit {0}:\n", kvp.Key); 407 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
408 }
409
410 sb.Append(cdt.ToString());
411 */
412 }
413
414 private void BuildSummaryStatsByCapReport(StringBuilder sb)
415 {
416 /*
417 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
418 cdt.AddColumn("Name", 34);
419 cdt.AddColumn("Req Received", 12);
420 cdt.AddColumn("Req Handled", 12);
421 cdt.Indent = 2;
422
423 Dictionary<string, int> receivedStats = new Dictionary<string, int>();
424 Dictionary<string, int> handledStats = new Dictionary<string, int>();
254 425
255 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 426 m_scene.ForEachScenePresence(
427 sp =>
256 { 428 {
257 Uri uri = new Uri(kvp2.Value.ToString()); 429 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
258 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); 430
431 if (caps == null)
432 return;
433
434 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
435 {
436 string reqName = reqHandler.Name ?? "";
437
438 if (!receivedStats.ContainsKey(reqName))
439 {
440 receivedStats[reqName] = reqHandler.RequestsReceived;
441 handledStats[reqName] = reqHandler.RequestsHandled;
442 }
443 else
444 {
445 receivedStats[reqName] += reqHandler.RequestsReceived;
446 handledStats[reqName] += reqHandler.RequestsHandled;
447 }
448 }
449
450 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
451 {
452 string name = kvp.Key;
453 PollServiceEventArgs pollHandler = kvp.Value;
454
455 if (!receivedStats.ContainsKey(name))
456 {
457 receivedStats[name] = pollHandler.RequestsReceived;
458 handledStats[name] = pollHandler.RequestsHandled;
459 }
460 else
461 {
462 receivedStats[name] += pollHandler.RequestsReceived;
463 handledStats[name] += pollHandler.RequestsHandled;
464 }
465 }
259 } 466 }
467 );
468
469 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
470 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
471
472 sb.Append(cdt.ToString());
473 */
474 }
475
476 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams)
477 {
478 /*
479 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
480 return;
481
482 if (cmdParams.Length != 5 && cmdParams.Length != 7)
483 {
484 MainConsole.Instance.Output("Usage: show caps stats by user [<first-name> <last-name>]");
485 return;
486 }
487
488 StringBuilder sb = new StringBuilder();
489 sb.AppendFormat("Region {0}:\n", m_scene.Name);
490
491 if (cmdParams.Length == 5)
492 {
493 BuildSummaryStatsByUserReport(sb);
494 }
495 else if (cmdParams.Length == 7)
496 {
497 string firstName = cmdParams[5];
498 string lastName = cmdParams[6];
499
500 ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
260 501
261 foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) 502 if (sp == null)
262 caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value); 503 return;
504
505 BuildDetailedStatsByUserReport(sb, sp);
263 } 506 }
264 507
265 MainConsole.Instance.Output(caps.ToString()); 508 MainConsole.Instance.Output(sb.ToString());
509 */
510 }
511
512 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp)
513 {
514 /*
515 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root");
516
517 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
518 cdt.AddColumn("Cap Name", 34);
519 cdt.AddColumn("Req Received", 12);
520 cdt.AddColumn("Req Handled", 12);
521 cdt.Indent = 2;
522
523 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
524
525 if (caps == null)
526 return;
527
528 List<CapTableRow> capRows = new List<CapTableRow>();
529
530 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
531 capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled));
532
533 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
534 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
535
536 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
537 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
538
539 sb.Append(cdt.ToString());
540 */
541 }
542
543 private void BuildSummaryStatsByUserReport(StringBuilder sb)
544 {
545 /*
546 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
547 cdt.AddColumn("Name", 32);
548 cdt.AddColumn("Type", 5);
549 cdt.AddColumn("Req Received", 12);
550 cdt.AddColumn("Req Handled", 12);
551 cdt.Indent = 2;
552
553 m_scene.ForEachScenePresence(
554 sp =>
555 {
556 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
557
558 if (caps == null)
559 return;
560
561 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
562
563 int totalRequestsReceived = 0;
564 int totalRequestsHandled = 0;
565
566 foreach (IRequestHandler reqHandler in capsHandlers.Values)
567 {
568 totalRequestsReceived += reqHandler.RequestsReceived;
569 totalRequestsHandled += reqHandler.RequestsHandled;
570 }
571
572 Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers();
573
574 foreach (PollServiceEventArgs handler in capsPollHandlers.Values)
575 {
576 totalRequestsReceived += handler.RequestsReceived;
577 totalRequestsHandled += handler.RequestsHandled;
578 }
579
580 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
581 }
582 );
583
584 sb.Append(cdt.ToString());
585 */
586 }
587
588 private class CapTableRow
589 {
590 public string Name { get; set; }
591 public int RequestsReceived { get; set; }
592 public int RequestsHandled { get; set; }
593
594 public CapTableRow(string name, int requestsReceived, int requestsHandled)
595 {
596 Name = name;
597 RequestsReceived = requestsReceived;
598 RequestsHandled = requestsHandled;
599 }
266 } 600 }
267 } 601 }
268} 602}
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
index 1f1568f..0c632b1 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
@@ -44,11 +44,12 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
45 public class DAExampleModule : INonSharedRegionModule 45 public class DAExampleModule : INonSharedRegionModule
46 { 46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private static readonly bool ENABLED = false; // enable for testing 49 private readonly bool ENABLED = false; // enable for testing
50 50
51 public const string DANamespace = "DAExample Module"; 51 public const string Namespace = "Example";
52 public const string StoreName = "DA";
52 53
53 protected Scene m_scene; 54 protected Scene m_scene;
54 protected IDialogModule m_dialogMod; 55 protected IDialogModule m_dialogMod;
@@ -65,6 +66,8 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
65 m_scene = scene; 66 m_scene = scene;
66 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; 67 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove;
67 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); 68 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>();
69
70 m_log.DebugFormat("[DA EXAMPLE MODULE]: Added region {0}", m_scene.Name);
68 } 71 }
69 } 72 }
70 73
@@ -91,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
91 if (sop == null) 94 if (sop == null)
92 return true; 95 return true;
93 96
94 if (!sop.DynAttrs.TryGetValue(DANamespace, out attrs)) 97 if (!sop.DynAttrs.TryGetStore(Namespace, StoreName, out attrs))
95 attrs = new OSDMap(); 98 attrs = new OSDMap();
96 99
97 OSDInteger newValue; 100 OSDInteger newValue;
@@ -106,12 +109,14 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
106 109
107 attrs["moves"] = newValue; 110 attrs["moves"] = newValue;
108 111
109 sop.DynAttrs[DANamespace] = attrs; 112 sop.DynAttrs.SetStore(Namespace, StoreName, attrs);
110 } 113 }
111 114
112 sop.ParentGroup.HasGroupChanged = true; 115 sop.ParentGroup.HasGroupChanged = true;
113 116
114 m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); 117 string msg = string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue);
118 m_log.DebugFormat("[DA EXAMPLE MODULE]: {0}", msg);
119 m_dialogMod.SendGeneralAlert(msg);
115 120
116 return true; 121 return true;
117 } 122 }
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
index 650aa35..166a994 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
@@ -64,8 +64,8 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
64 64
65 private Scene m_scene; 65 private Scene m_scene;
66 private IDialogModule m_dialogMod; 66 private IDialogModule m_dialogMod;
67 67
68 public string Name { get { return "DOExample Module"; } } 68 public string Name { get { return "DO"; } }
69 public Type ReplaceableInterface { get { return null; } } 69 public Type ReplaceableInterface { get { return null; } }
70 70
71 public void Initialise(IConfigSource source) {} 71 public void Initialise(IConfigSource source) {}
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
106 106
107// Console.WriteLine("Here for {0}", so.Name); 107// Console.WriteLine("Here for {0}", so.Name);
108 108
109 if (rootPart.DynAttrs.TryGetValue(DAExampleModule.DANamespace, out attrs)) 109 if (rootPart.DynAttrs.TryGetStore(DAExampleModule.Namespace, DAExampleModule.StoreName, out attrs))
110 { 110 {
111 movesSoFar = attrs["moves"].AsInteger(); 111 movesSoFar = attrs["moves"].AsInteger();
112 112
@@ -114,7 +114,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
114 "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name); 114 "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name);
115 } 115 }
116 116
117 rootPart.DynObjs.Add(Name, new MyObject(movesSoFar)); 117 rootPart.DynObjs.Add(DAExampleModule.Namespace, Name, new MyObject(movesSoFar));
118 } 118 }
119 119
120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta) 120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ed867b8..d5eca03 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -52,10 +52,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule 52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
55 56
56 public const int DefaultMaxTransferDistance = 4095; 57 public const int DefaultMaxTransferDistance = 4095;
57 public const bool WaitForAgentArrivedAtDestinationDefault = true; 58 public const bool WaitForAgentArrivedAtDestinationDefault = true;
58 59
60 public string OutgoingTransferVersionName { get; set; }
61
62 /// <summary>
63 /// Determine the maximum entity transfer version we will use for teleports.
64 /// </summary>
65 public float MaxOutgoingTransferVersion { get; set; }
66
59 /// <summary> 67 /// <summary>
60 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. 68 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
61 /// </summary> 69 /// </summary>
@@ -151,9 +159,39 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
151 /// <param name="source"></param> 159 /// <param name="source"></param>
152 protected virtual void InitialiseCommon(IConfigSource source) 160 protected virtual void InitialiseCommon(IConfigSource source)
153 { 161 {
162 string transferVersionName = "SIMULATION";
163 float maxTransferVersion = 0.2f;
164
154 IConfig transferConfig = source.Configs["EntityTransfer"]; 165 IConfig transferConfig = source.Configs["EntityTransfer"];
155 if (transferConfig != null) 166 if (transferConfig != null)
156 { 167 {
168 string rawVersion
169 = transferConfig.GetString(
170 "MaxOutgoingTransferVersion",
171 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
172
173 string[] rawVersionComponents = rawVersion.Split(new char[] { '/' });
174
175 bool versionValid = false;
176
177 if (rawVersionComponents.Length >= 2)
178 versionValid = float.TryParse(rawVersionComponents[1], out maxTransferVersion);
179
180 if (!versionValid)
181 {
182 m_log.ErrorFormat(
183 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion {0} is invalid, using {1}",
184 rawVersion, string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
185 }
186 else
187 {
188 transferVersionName = rawVersionComponents[0];
189
190 m_log.InfoFormat(
191 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion set to {0}",
192 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
193 }
194
157 DisableInterRegionTeleportCancellation 195 DisableInterRegionTeleportCancellation
158 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); 196 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
159 197
@@ -167,6 +205,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
167 MaxTransferDistance = DefaultMaxTransferDistance; 205 MaxTransferDistance = DefaultMaxTransferDistance;
168 } 206 }
169 207
208 OutgoingTransferVersionName = transferVersionName;
209 MaxOutgoingTransferVersion = maxTransferVersion;
210
170 m_entityTransferStateMachine = new EntityTransferStateMachine(this); 211 m_entityTransferStateMachine = new EntityTransferStateMachine(this);
171 212
172 m_Enabled = true; 213 m_Enabled = true;
@@ -280,10 +321,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
280 321
281 private void OnConnectionClosed(IClientAPI client) 322 private void OnConnectionClosed(IClientAPI client)
282 { 323 {
283 if (client.IsLoggingOut) 324 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting))
284 { 325 {
285 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
286
287 m_log.DebugFormat( 326 m_log.DebugFormat(
288 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", 327 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
289 client.Name, Scene.Name); 328 client.Name, Scene.Name);
@@ -318,7 +357,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
318 m_log.DebugFormat( 357 m_log.DebugFormat(
319 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.", 358 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.",
320 sp.Name, sp.UUID, position, regionHandle); 359 sp.Name, sp.UUID, position, regionHandle);
321 360
361 sp.ControllingClient.SendTeleportFailed("Previous teleport process incomplete. Please retry shortly.");
362
322 return; 363 return;
323 } 364 }
324 365
@@ -389,7 +430,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
389 } 430 }
390 431
391 // TODO: Get proper AVG Height 432 // TODO: Get proper AVG Height
392 float localAVHeight = 1.56f; 433 float localHalfAVHeight = 0.8f;
434 if (sp.Appearance != null)
435 localHalfAVHeight = sp.Appearance.AvatarHeight / 2;
436
393 float posZLimit = 22; 437 float posZLimit = 22;
394 438
395 // TODO: Check other Scene HeightField 439 // TODO: Check other Scene HeightField
@@ -398,10 +442,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
398 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; 442 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
399 } 443 }
400 444
401 float newPosZ = posZLimit + localAVHeight; 445 posZLimit += localHalfAVHeight + 0.1f;
402 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 446
447 if ((position.Z < posZLimit) && !(Single.IsInfinity(posZLimit) || Single.IsNaN(posZLimit)))
403 { 448 {
404 position.Z = newPosZ; 449 position.Z = posZLimit;
405 } 450 }
406 451
407 if (sp.Flying) 452 if (sp.Flying)
@@ -522,6 +567,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
522 /// </returns> 567 /// </returns>
523 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion) 568 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
524 { 569 {
570 if(MaxTransferDistance == 0)
571 return true;
572
525// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); 573// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
526// 574//
527// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", 575// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
@@ -623,7 +671,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
623 if (!sp.ValidateAttachments()) 671 if (!sp.ValidateAttachments())
624 m_log.DebugFormat( 672 m_log.DebugFormat(
625 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", 673 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
626 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); 674 sp.Name, sp.Scene.Name, finalDestination.RegionName);
627 675
628 string reason; 676 string reason;
629 string version; 677 string version;
@@ -634,7 +682,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
634 682
635 m_log.DebugFormat( 683 m_log.DebugFormat(
636 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", 684 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
637 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 685 sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);
638 686
639 return; 687 return;
640 } 688 }
@@ -644,7 +692,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
644 // as server attempts. 692 // as server attempts.
645 m_interRegionTeleportAttempts.Value++; 693 m_interRegionTeleportAttempts.Value++;
646 694
647 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 695 m_log.DebugFormat(
696 "[ENTITY TRANSFER MODULE]: {0} max transfer version is {1}/{2}, {3} max version is {4}",
697 sp.Scene.Name, OutgoingTransferVersionName, MaxOutgoingTransferVersion, finalDestination.RegionName, version);
648 698
649 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 699 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
650 // both regions 700 // both regions
@@ -674,7 +724,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
674 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); 724 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
675 agentCircuit.startpos = position; 725 agentCircuit.startpos = position;
676 agentCircuit.child = true; 726 agentCircuit.child = true;
677 agentCircuit.Appearance = sp.Appearance; 727
728// agentCircuit.Appearance = sp.Appearance;
729// agentCircuit.Appearance = new AvatarAppearance(sp.Appearance, true, false);
730 agentCircuit.Appearance = new AvatarAppearance();
731 agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
732
678 if (currentAgentCircuit != null) 733 if (currentAgentCircuit != null)
679 { 734 {
680 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; 735 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -691,6 +746,29 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
691 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 746 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
692 } 747 }
693 748
749 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 or we're forcing
750 // use of the earlier protocol
751 float versionNumber = 0.1f;
752 string[] versionComponents = version.Split(new char[] { '/' });
753 if (versionComponents.Length >= 2)
754 float.TryParse(versionComponents[1], out versionNumber);
755
756 if (versionNumber == 0.2f && MaxOutgoingTransferVersion >= versionNumber)
757 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
758 else
759 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
760 }
761
762 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
763 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
764 {
765 ulong destinationHandle = finalDestination.RegionHandle;
766 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
767
768 m_log.DebugFormat(
769 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
770 sp.Name, Scene.Name, finalDestination.RegionName);
771
694 // Let's create an agent there if one doesn't exist yet. 772 // Let's create an agent there if one doesn't exist yet.
695 // NOTE: logout will always be false for a non-HG teleport. 773 // NOTE: logout will always be false for a non-HG teleport.
696 bool logout = false; 774 bool logout = false;
@@ -712,7 +790,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
712 m_interRegionTeleportCancels.Value++; 790 m_interRegionTeleportCancels.Value++;
713 791
714 m_log.DebugFormat( 792 m_log.DebugFormat(
715 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 793 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
716 sp.Name, finalDestination.RegionName, sp.Scene.Name); 794 sp.Name, finalDestination.RegionName, sp.Scene.Name);
717 795
718 return; 796 return;
@@ -734,11 +812,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
734 // OK, it got this agent. Let's close some child agents 812 // OK, it got this agent. Let's close some child agents
735 sp.CloseChildAgents(newRegionX, newRegionY); 813 sp.CloseChildAgents(newRegionX, newRegionY);
736 814
737 IClientIPEndpoint ipepClient; 815 IClientIPEndpoint ipepClient;
816 string capsPath = String.Empty;
738 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 817 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
739 { 818 {
740 m_log.DebugFormat( 819 m_log.DebugFormat(
741 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", 820 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
742 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); 821 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
743 822
744 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); 823 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
@@ -756,7 +835,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
756 // The EnableSimulator message makes the client establish a connection with the destination 835 // The EnableSimulator message makes the client establish a connection with the destination
757 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the 836 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
758 // correct circuit code. 837 // correct circuit code.
759 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); 838 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID,
839 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
840 m_log.DebugFormat("{0} Sent EnableSimulator. regName={1}, size=<{2},{3}>", LogHeader,
841 finalDestination.RegionName, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
760 842
761 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination 843 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
762 // simulator to confirm that it has established communication with the viewer. 844 // simulator to confirm that it has established communication with the viewer.
@@ -766,7 +848,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
766 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly 848 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
767 // only on TeleportFinish). This is untested for region teleport between different simulators 849 // only on TeleportFinish). This is untested for region teleport between different simulators
768 // though this probably also works. 850 // though this probably also works.
769 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 851 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, finalDestination.RegionHandle,
852 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
770 } 853 }
771 else 854 else
772 { 855 {
@@ -785,10 +868,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
785 // Let's send a full update of the agent. This is a synchronous call. 868 // Let's send a full update of the agent. This is a synchronous call.
786 AgentData agent = new AgentData(); 869 AgentData agent = new AgentData();
787 sp.CopyTo(agent); 870 sp.CopyTo(agent);
788 agent.Position = position; 871 agent.Position = agentCircuit.startpos;
789 SetCallbackURL(agent, sp.Scene.RegionInfo); 872 SetCallbackURL(agent, sp.Scene.RegionInfo);
790 873
791 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
792 874
793 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to 875 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
794 // establish th econnection to the destination which makes it return true. 876 // establish th econnection to the destination which makes it return true.
@@ -821,10 +903,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
821 } 903 }
822 904
823 m_log.WarnFormat( 905 m_log.WarnFormat(
824 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", 906 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
825 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 907 sp.Name, finalDestination.RegionName, sp.Scene.Name);
826 908
827 Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established."); 909 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
828 return; 910 return;
829 } 911 }
830 912
@@ -833,10 +915,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
833 m_interRegionTeleportCancels.Value++; 915 m_interRegionTeleportCancels.Value++;
834 916
835 m_log.DebugFormat( 917 m_log.DebugFormat(
836 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", 918 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
837 sp.Name, finalDestination.RegionName, sp.Scene.Name); 919 sp.Name, finalDestination.RegionName, sp.Scene.Name);
838 920
839 CleanupFailedInterRegionTeleport(sp, finalDestination); 921 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
840 922
841 return; 923 return;
842 } 924 }
@@ -850,9 +932,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
850 // closes our existing agent which is still signalled as root. 932 // closes our existing agent which is still signalled as root.
851 sp.IsChildAgent = true; 933 sp.IsChildAgent = true;
852 934
935 // OK, send TPFinish to the client, so that it starts the process of contacting the destination region
853 if (m_eqModule != null) 936 if (m_eqModule != null)
854 { 937 {
855 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); 938 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
939 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
856 } 940 }
857 else 941 else
858 { 942 {
@@ -879,8 +963,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
879 m_log.WarnFormat( 963 m_log.WarnFormat(
880 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", 964 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
881 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 965 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
882 966
883 Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); 967 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
884 968
885 return; 969 return;
886 } 970 }
@@ -896,7 +980,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
896 } 980 }
897 981
898 // May need to logout or other cleanup 982 // May need to logout or other cleanup
899 AgentHasMovedAway(sp, logout); 983// AgentHasMovedAway(sp, logout);
984 AgentHasMovedAway(sp, true); // until logout use is checked
900 985
901 // Well, this is it. The agent is over there. 986 // Well, this is it. The agent is over there.
902 KillEntity(sp.Scene, sp.LocalId); 987 KillEntity(sp.Scene, sp.LocalId);
@@ -908,15 +993,191 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
908 993
909 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 994 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
910 { 995 {
996 if (!sp.Scene.IncomingPreCloseClient(sp))
997 return;
998
911 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before 999 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
912 // they regard the new region as the current region after receiving the AgentMovementComplete 1000 // they regard the new region as the current region after receiving the AgentMovementComplete
913 // response. If close is sent before then, it will cause the viewer to quit instead. 1001 // response. If close is sent before then, it will cause the viewer to quit instead.
914 // 1002 //
915 // This sleep can be increased if necessary. However, whilst it's active, 1003 // This sleep can be increased if necessary. However, whilst it's active,
916 // an agent cannot teleport back to this region if it has teleported away. 1004 // an agent cannot teleport back to this region if it has teleported away.
917 Thread.Sleep(3000); 1005 Thread.Sleep(2000);
1006
1007 sp.Scene.CloseAgent(sp.UUID, false);
1008 }
1009 else
1010 {
1011 // now we have a child agent in this region.
1012 sp.Reset();
1013 }
1014 }
1015
1016 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1017 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
1018 {
1019 ulong destinationHandle = finalDestination.RegionHandle;
1020 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1021
1022 // Let's create an agent there if one doesn't exist yet.
1023 // NOTE: logout will always be false for a non-HG teleport.
1024 bool logout = false;
1025 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
1026 {
1027 m_interRegionTeleportFailures.Value++;
1028
1029 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
1030
1031 m_log.DebugFormat(
1032 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
1033 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
1034
1035 return;
1036 }
1037
1038 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
1039 {
1040 m_interRegionTeleportCancels.Value++;
1041
1042 m_log.DebugFormat(
1043 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
1044 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1045
1046 return;
1047 }
1048 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1049 {
1050 m_interRegionTeleportAborts.Value++;
1051
1052 m_log.DebugFormat(
1053 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
1054 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1055
1056 return;
1057 }
1058
1059 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1060 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1061
1062 IClientIPEndpoint ipepClient;
1063 string capsPath = String.Empty;
1064 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
1065 {
1066 m_log.DebugFormat(
1067 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1068 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1069
1070 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1071 #region IP Translation for NAT
1072 // Uses ipepClient above
1073 if (sp.ClientView.TryGet(out ipepClient))
1074 {
1075 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1076 }
1077 #endregion
1078 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1079 }
1080 else
1081 {
1082 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1083 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1084 }
1085
1086 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1087 // where that neighbour simulator could otherwise request a child agent create on the source which then
1088 // closes our existing agent which is still signalled as root.
1089 //sp.IsChildAgent = true;
1090
1091 // New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid
1092 if (m_eqModule != null)
1093 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
1094 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1095 else
1096 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
1097 teleportFlags, capsPath);
1098
1099 m_log.DebugFormat(
1100 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
1101 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
918 1102
919 sp.Scene.IncomingCloseAgent(sp.UUID, false); 1103 // Let's send a full update of the agent.
1104 AgentData agent = new AgentData();
1105 sp.CopyTo(agent);
1106 agent.Position = agentCircuit.startpos;
1107 agent.SenderWantsToWaitForRoot = true;
1108 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1109
1110 // Reset the do not close flag. This must be done before the destination opens child connections (here
1111 // triggered by UpdateAgent) to avoid race conditions. However, we also want to reset it as late as possible
1112 // to avoid a situation where an unexpectedly early call to Scene.NewUserConnection() wrongly results
1113 // in no close.
1114 sp.DoNotCloseAfterTeleport = false;
1115
1116 // Send the Update. If this returns true, we know the client has contacted the destination
1117 // via CompleteMovementIntoRegion, so we can let go.
1118 // If it returns false, something went wrong, and we need to abort.
1119 if (!UpdateAgent(reg, finalDestination, agent, sp))
1120 {
1121 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1122 {
1123 m_interRegionTeleportAborts.Value++;
1124
1125 m_log.DebugFormat(
1126 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
1127 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1128
1129 return;
1130 }
1131
1132 m_log.WarnFormat(
1133 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1134 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1135
1136 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
1137 return;
1138 }
1139
1140 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1141
1142 // Need to signal neighbours whether child agents may need closing irrespective of whether this
1143 // one needed closing. We also need to close child agents as quickly as possible to avoid complicated
1144 // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back
1145 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex
1146 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are
1147 // abandoned without proper close by viewer but then re-used by an incoming connection.
1148 sp.CloseChildAgents(newRegionX, newRegionY);
1149
1150 // May need to logout or other cleanup
1151// AgentHasMovedAway(sp, logout);
1152 AgentHasMovedAway(sp, true);
1153
1154 // Well, this is it. The agent is over there.
1155 KillEntity(sp.Scene, sp.LocalId);
1156
1157 // Now let's make it officially a child agent
1158 sp.MakeChildAgent();
1159
1160 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1161 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1162 {
1163 if (!sp.Scene.IncomingPreCloseClient(sp))
1164 return;
1165
1166 // RED ALERT!!!!
1167 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES.
1168 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion
1169 // BEFORE THEY SETTLE IN THE NEW REGION.
1170 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1171 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1172 Thread.Sleep(15000);
1173
1174 // OK, it got this agent. Let's close everything
1175 // If we shouldn't close the agent due to some other region renewing the connection
1176 // then this will be handled in IncomingCloseAgent under lock conditions
1177 m_log.DebugFormat(
1178 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1179
1180 sp.Scene.CloseAgent(sp.UUID, false);
920 } 1181 }
921 else 1182 else
922 { 1183 {
@@ -934,17 +1195,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
934 /// <remarks> 1195 /// <remarks>
935 /// <param name='sp'> </param> 1196 /// <param name='sp'> </param>
936 /// <param name='finalDestination'></param> 1197 /// <param name='finalDestination'></param>
937 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) 1198 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, string auth_token, GridRegion finalDestination)
938 { 1199 {
939 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 1200 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
940 1201
941 sp.IsChildAgent = false; 1202 if (sp.IsChildAgent) // We had set it to child before attempted TP (V1)
942 ReInstantiateScripts(sp); 1203 {
943 1204 sp.IsChildAgent = false;
944 EnableChildAgents(sp); 1205 ReInstantiateScripts(sp);
945 1206
1207 EnableChildAgents(sp);
1208 }
946 // Finally, kill the agent we just created at the destination. 1209 // Finally, kill the agent we just created at the destination.
947 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); 1210 // XXX: Possibly this should be done asynchronously.
1211 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token);
948 } 1212 }
949 1213
950 /// <summary> 1214 /// <summary>
@@ -954,9 +1218,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
954 /// <param name='finalDestination'></param> 1218 /// <param name='finalDestination'></param>
955 /// <param name='logout'></param> 1219 /// <param name='logout'></param>
956 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> 1220 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
957 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) 1221 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string auth_code, string reason)
958 { 1222 {
959 CleanupFailedInterRegionTeleport(sp, finalDestination); 1223 CleanupFailedInterRegionTeleport(sp, auth_code, finalDestination);
960 1224
961 m_interRegionTeleportFailures.Value++; 1225 m_interRegionTeleportFailures.Value++;
962 1226
@@ -1000,7 +1264,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1000 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) 1264 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
1001 { 1265 {
1002 if (sp.Scene.AttachmentsModule != null) 1266 if (sp.Scene.AttachmentsModule != null)
1003 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true); 1267 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, logout);
1004 } 1268 }
1005 1269
1006 protected void KillEntity(Scene scene, uint localID) 1270 protected void KillEntity(Scene scene, uint localID)
@@ -1128,11 +1392,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1128 1392
1129 1393
1130 #region Agent Crossings 1394 #region Agent Crossings
1131
1132 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) 1395 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
1133 { 1396 {
1397 string r = String.Empty;
1398 return GetDestination(scene, agentID, pos, out xDest, out yDest, out version, out newpos, out r);
1399 }
1400
1401 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos, out string reason)
1402 {
1134 version = String.Empty; 1403 version = String.Empty;
1135 newpos = new Vector3(pos.X, pos.Y, pos.Z); 1404 reason = String.Empty;
1405 newpos = pos;
1136 1406
1137// m_log.DebugFormat( 1407// m_log.DebugFormat(
1138// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1408// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
@@ -1245,8 +1515,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1245 } 1515 }
1246 1516
1247 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); 1517 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
1248 1518
1249 string reason;
1250 if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) 1519 if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
1251 { 1520 {
1252 if (r == null) 1521 if (r == null)
@@ -1272,11 +1541,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1272 uint y; 1541 uint y;
1273 Vector3 newpos; 1542 Vector3 newpos;
1274 string version; 1543 string version;
1544 string reason;
1275 1545
1276 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos); 1546 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos, out reason);
1277 if (neighbourRegion == null) 1547 if (neighbourRegion == null)
1278 { 1548 {
1279 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); 1549 if (reason == String.Empty)
1550 agent.ControllingClient.SendAlertMessage("Cannot cross to region");
1551 else
1552 agent.ControllingClient.SendAlertMessage("Cannot cross to region: " + reason);
1280 return false; 1553 return false;
1281 } 1554 }
1282 1555
@@ -1403,10 +1676,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1403 1676
1404 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) 1677 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying)
1405 { 1678 {
1679 int ts = Util.EnvironmentTickCount();
1406 try 1680 try
1407 { 1681 {
1682
1408 AgentData cAgent = new AgentData(); 1683 AgentData cAgent = new AgentData();
1409 agent.CopyTo(cAgent); 1684 agent.CopyTo(cAgent);
1685
1686// agent.Appearance.WearableCacheItems = null;
1687
1410 cAgent.Position = pos + agent.Velocity; 1688 cAgent.Position = pos + agent.Velocity;
1411 if (isFlying) 1689 if (isFlying)
1412 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; 1690 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
@@ -1427,11 +1705,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1427 neighbourRegion.RegionName, agent.Name); 1705 neighbourRegion.RegionName, agent.Name);
1428 1706
1429 ReInstantiateScripts(agent); 1707 ReInstantiateScripts(agent);
1430 agent.AddToPhysicalScene(isFlying); 1708 if(agent.ParentID == 0 && agent.ParentUUID == UUID.Zero)
1709 agent.AddToPhysicalScene(isFlying);
1431 1710
1432 return false; 1711 return false;
1433 } 1712 }
1434 1713
1714 m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts));
1715
1435 } 1716 }
1436 catch (Exception e) 1717 catch (Exception e)
1437 { 1718 {
@@ -1449,6 +1730,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1449 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, 1730 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1450 bool isFlying, string version) 1731 bool isFlying, string version)
1451 { 1732 {
1733
1452 agent.ControllingClient.RequestClientInfo(); 1734 agent.ControllingClient.RequestClientInfo();
1453 1735
1454 string agentcaps; 1736 string agentcaps;
@@ -1460,6 +1742,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1460 } 1742 }
1461 1743
1462 // No turning back 1744 // No turning back
1745
1746
1747
1463 agent.IsChildAgent = true; 1748 agent.IsChildAgent = true;
1464 1749
1465 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1750 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
@@ -1471,21 +1756,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1471 if (m_eqModule != null) 1756 if (m_eqModule != null)
1472 { 1757 {
1473 m_eqModule.CrossRegion( 1758 m_eqModule.CrossRegion(
1474 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, 1759 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */,
1475 capsPath, agent.UUID, agent.ControllingClient.SessionId); 1760 neighbourRegion.ExternalEndPoint,
1761 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1762 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1476 } 1763 }
1477 else 1764 else
1478 { 1765 {
1766 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1479 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1767 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint,
1480 capsPath); 1768 capsPath);
1481 } 1769 }
1482 1770
1771 // Backwards compatibility. Best effort
1772 if (version == "Unknown" || version == string.Empty)
1773 {
1774 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1775 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1776 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1777 }
1778
1483 // SUCCESS! 1779 // SUCCESS!
1484 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); 1780 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
1485 1781
1486 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. 1782 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1487 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1783 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1488 1784
1785 // this may need the attachments
1786 agent.parcelRegionCross();
1787
1788 AgentHasMovedAway(agent, true);
1789
1489 agent.MakeChildAgent(); 1790 agent.MakeChildAgent();
1490 1791
1491 // FIXME: Possibly this should occur lower down after other commands to close other agents, 1792 // FIXME: Possibly this should occur lower down after other commands to close other agents,
@@ -1493,16 +1794,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1493 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1794 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1494 1795
1495 // now we have a child agent in this region. Request all interesting data about other (root) agents 1796 // now we have a child agent in this region. Request all interesting data about other (root) agents
1496 agent.SendOtherAgentsAvatarDataToMe();
1497 agent.SendOtherAgentsAppearanceToMe();
1498 1797
1499 // Backwards compatibility. Best effort 1798 // why do that? we either where a root having all that or we are leaving the area
1500 if (version == "Unknown" || version == string.Empty) 1799
1501 { 1800// agent.SendOtherAgentsAvatarDataToMe();
1502 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); 1801// agent.SendOtherAgentsAppearanceToMe();
1503 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1504 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1505 }
1506 1802
1507 // Next, let's close the child agent connections that are too far away. 1803 // Next, let's close the child agent connections that are too far away.
1508 uint neighbourx; 1804 uint neighbourx;
@@ -1515,7 +1811,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1515 1811
1516 agent.CloseChildAgents(neighbourx, neighboury); 1812 agent.CloseChildAgents(neighbourx, neighboury);
1517 1813
1518 AgentHasMovedAway(agent, false); 1814
1519 1815
1520 // the user may change their profile information in other region, 1816 // the user may change their profile information in other region,
1521 // so the userinfo in UserProfileCache is not reliable any more, delete it 1817 // so the userinfo in UserProfileCache is not reliable any more, delete it
@@ -1555,7 +1851,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1555 #region Enable Child Agent 1851 #region Enable Child Agent
1556 1852
1557 /// <summary> 1853 /// <summary>
1558 /// This informs a single neighbouring region about agent "avatar". 1854 /// This informs a single neighbouring region about agent "avatar", and avatar about it
1559 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1855 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1560 /// </summary> 1856 /// </summary>
1561 /// <param name="sp"></param> 1857 /// <param name="sp"></param>
@@ -1570,7 +1866,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1570 agent.InventoryFolder = UUID.Zero; 1866 agent.InventoryFolder = UUID.Zero;
1571 agent.startpos = new Vector3(128, 128, 70); 1867 agent.startpos = new Vector3(128, 128, 70);
1572 agent.child = true; 1868 agent.child = true;
1573 agent.Appearance = sp.Appearance; 1869
1870 agent.Appearance = new AvatarAppearance();
1871 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1872
1574 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 1873 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1575 1874
1576 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID)); 1875 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
@@ -1601,6 +1900,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1601 agent.Id0 = currentAgentCircuit.Id0; 1900 agent.Id0 = currentAgentCircuit.Id0;
1602 } 1901 }
1603 1902
1903 Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start
1904
1604 IPEndPoint external = region.ExternalEndPoint; 1905 IPEndPoint external = region.ExternalEndPoint;
1605 if (external != null) 1906 if (external != null)
1606 { 1907 {
@@ -1619,6 +1920,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1619 1920
1620 /// <summary> 1921 /// <summary>
1621 /// This informs all neighbouring regions about agent "avatar". 1922 /// This informs all neighbouring regions about agent "avatar".
1923 /// and as important informs the avatar about then
1622 /// </summary> 1924 /// </summary>
1623 /// <param name="sp"></param> 1925 /// <param name="sp"></param>
1624 public void EnableChildAgents(ScenePresence sp) 1926 public void EnableChildAgents(ScenePresence sp)
@@ -1635,81 +1937,77 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1635 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); 1937 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
1636 } 1938 }
1637 1939
1638 /// We need to find the difference between the new regions where there are no child agents 1940 LinkedList<ulong> previousRegionNeighbourHandles;
1639 /// and the regions where there are already child agents. We only send notification to the former. 1941
1640 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region 1942 Dictionary<ulong, string> seeds;
1641 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
1642 List<ulong> previousRegionNeighbourHandles;
1643 1943
1644 if (sp.Scene.CapsModule != null) 1944 if (sp.Scene.CapsModule != null)
1645 { 1945 {
1646 previousRegionNeighbourHandles = 1946 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1647 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys); 1947 previousRegionNeighbourHandles = new LinkedList<ulong>(seeds.Keys);
1648 } 1948 }
1649 else 1949 else
1650 { 1950 {
1651 previousRegionNeighbourHandles = new List<ulong>();
1652 }
1653
1654 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1655 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1656
1657 //Dump("Current Neighbors", neighbourHandles);
1658 //Dump("Previous Neighbours", previousRegionNeighbourHandles);
1659 //Dump("New Neighbours", newRegions);
1660 //Dump("Old Neighbours", oldRegions);
1661
1662 /// Update the scene presence's known regions here on this region
1663 sp.DropOldNeighbours(oldRegions);
1664
1665 /// Collect as many seeds as possible
1666 Dictionary<ulong, string> seeds;
1667 if (sp.Scene.CapsModule != null)
1668 seeds
1669 = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1670 else
1671 seeds = new Dictionary<ulong, string>(); 1951 seeds = new Dictionary<ulong, string>();
1952 previousRegionNeighbourHandles = new LinkedList<ulong>();
1953 }
1672 1954
1673 //m_log.Debug(" !!! No. of seeds: " + seeds.Count);
1674 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) 1955 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle))
1675 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath); 1956 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1676 1957
1677 /// Create the necessary child agents 1958 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1959
1960 List<ulong> newneighbours = new List<ulong>();
1678 List<AgentCircuitData> cagents = new List<AgentCircuitData>(); 1961 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
1962
1963 ulong currentRegionHandler = sp.Scene.RegionInfo.RegionHandle;
1964
1679 foreach (GridRegion neighbour in neighbours) 1965 foreach (GridRegion neighbour in neighbours)
1680 { 1966 {
1681 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 1967 ulong handler = neighbour.RegionHandle;
1682 {
1683 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1684 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1685 agent.BaseFolder = UUID.Zero;
1686 agent.InventoryFolder = UUID.Zero;
1687 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1688 agent.child = true;
1689 agent.Appearance = sp.Appearance;
1690 if (currentAgentCircuit != null)
1691 {
1692 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1693 agent.IPAddress = currentAgentCircuit.IPAddress;
1694 agent.Viewer = currentAgentCircuit.Viewer;
1695 agent.Channel = currentAgentCircuit.Channel;
1696 agent.Mac = currentAgentCircuit.Mac;
1697 agent.Id0 = currentAgentCircuit.Id0;
1698 }
1699 1968
1700 if (newRegions.Contains(neighbour.RegionHandle)) 1969 if (handler == currentRegionHandler)
1701 { 1970 continue;
1702 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 1971
1703 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath); 1972 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1704 seeds.Add(neighbour.RegionHandle, agent.CapsPath); 1973 agent.BaseFolder = UUID.Zero;
1705 } 1974 agent.InventoryFolder = UUID.Zero;
1706 else 1975 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1707 { 1976 agent.child = true;
1708 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle); 1977 agent.Appearance = new AvatarAppearance();
1709 } 1978 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1710 1979
1711 cagents.Add(agent); 1980 if (currentAgentCircuit != null)
1981 {
1982 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1983 agent.IPAddress = currentAgentCircuit.IPAddress;
1984 agent.Viewer = currentAgentCircuit.Viewer;
1985 agent.Channel = currentAgentCircuit.Channel;
1986 agent.Mac = currentAgentCircuit.Mac;
1987 agent.Id0 = currentAgentCircuit.Id0;
1988 }
1989
1990 if (previousRegionNeighbourHandles.Contains(handler))
1991 {
1992 previousRegionNeighbourHandles.Remove(handler);
1993 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, handler);
1712 } 1994 }
1995 else
1996 {
1997 newneighbours.Add(handler);
1998 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1999 sp.AddNeighbourRegion(handler, agent.CapsPath);
2000 seeds.Add(handler, agent.CapsPath);
2001 }
2002
2003 cagents.Add(agent);
2004 }
2005
2006 //sp.DropOldNeighbours(previousRegionNeighbourHandles);
2007 foreach (ulong handle in previousRegionNeighbourHandles)
2008 {
2009 sp.RemoveNeighbourRegion(handle);
2010 Scene.CapsModule.DropChildSeed(sp.UUID, handle);
1713 } 2011 }
1714 2012
1715 /// Update all child agent with everyone's seeds 2013 /// Update all child agent with everyone's seeds
@@ -1722,33 +2020,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1722 { 2020 {
1723 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds); 2021 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1724 } 2022 }
2023
1725 sp.KnownRegions = seeds; 2024 sp.KnownRegions = seeds;
1726 //avatar.Scene.DumpChildrenSeeds(avatar.UUID); 2025 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
1727 //avatar.DumpKnownRegions(); 2026 //avatar.DumpKnownRegions();
1728 2027
1729 bool newAgent = false; 2028 Util.FireAndForget(delegate
1730 int count = 0;
1731 foreach (GridRegion neighbour in neighbours)
1732 { 2029 {
1733 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName); 2030 Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start
1734 // Don't do it if there's already an agent in that region 2031 int count = 0;
1735 if (newRegions.Contains(neighbour.RegionHandle)) 2032 bool newagent;
1736 newAgent = true;
1737 else
1738 newAgent = false;
1739 2033
1740 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2034 foreach (GridRegion neighbour in neighbours)
1741 { 2035 {
1742 try 2036 try
1743 { 2037 {
1744 // Let's put this back at sync, so that it doesn't clog 2038 newagent = newneighbours.Contains(neighbour.RegionHandle);
1745 // the network, especially for regions in the same physical server. 2039 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newagent);
1746 // We're really not in a hurry here.
1747 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent);
1748 //InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1749 //d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1750 // InformClientOfNeighbourCompleted,
1751 // d);
1752 } 2040 }
1753 2041
1754 catch (ArgumentOutOfRangeException) 2042 catch (ArgumentOutOfRangeException)
@@ -1756,9 +2044,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1756 m_log.ErrorFormat( 2044 m_log.ErrorFormat(
1757 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", 2045 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).",
1758 neighbour.ExternalHostName, 2046 neighbour.ExternalHostName,
1759 neighbour.RegionHandle, 2047 neighbour.RegionHandle,
1760 neighbour.RegionLocX, 2048 neighbour.RegionLocX,
1761 neighbour.RegionLocY); 2049 neighbour.RegionLocY);
1762 } 2050 }
1763 catch (Exception e) 2051 catch (Exception e)
1764 { 2052 {
@@ -1775,11 +2063,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1775 2063
1776 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes. 2064 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
1777 // throw e; 2065 // throw e;
1778
1779 } 2066 }
2067 count++;
1780 } 2068 }
1781 count++; 2069 });
1782 }
1783 } 2070 }
1784 2071
1785 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2072 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
@@ -1813,11 +2100,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1813 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg, 2100 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg,
1814 IPEndPoint endPoint, bool newAgent) 2101 IPEndPoint endPoint, bool newAgent)
1815 { 2102 {
1816 // Let's wait just a little to give time to originating regions to catch up with closing child agents 2103 Scene scene = sp.Scene;
1817 // after a cross here 2104 if (!newAgent)
1818 Thread.Sleep(500); 2105 return;
1819
1820 Scene scene = sp.Scene;
1821 2106
1822 m_log.DebugFormat( 2107 m_log.DebugFormat(
1823 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})", 2108 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
@@ -1831,6 +2116,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1831 2116
1832 if (regionAccepted && newAgent) 2117 if (regionAccepted && newAgent)
1833 { 2118 {
2119 // give time for createAgent to finish, since it is async and does grid services access
2120 Thread.Sleep(500);
2121
1834 if (m_eqModule != null) 2122 if (m_eqModule != null)
1835 { 2123 {
1836 #region IP Translation for NAT 2124 #region IP Translation for NAT
@@ -1841,12 +2129,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1841 } 2129 }
1842 #endregion 2130 #endregion
1843 2131
1844 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbour region {2} @ {3} " + 2132 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
1845 "and EstablishAgentCommunication with seed cap {4}", 2133 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
1846 scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath); 2134 scene.RegionInfo.RegionName, sp.Name,
2135 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath);
1847 2136
1848 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID); 2137 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
1849 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 2138 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
1850 } 2139 }
1851 else 2140 else
1852 { 2141 {
@@ -2014,19 +2303,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2014 if (scene == null) 2303 if (scene == null)
2015 return; 2304 return;
2016 2305
2017 if (grp.RootPart.DIE_AT_EDGE) 2306// http://wiki.secondlife.com/wiki/STATUS_DIE_AT_EDGE
2018 { 2307// DieAtEdge does NOT mean that objects can't cross regions.
2019 // We remove the object here 2308// It just means they die when they go off world, unless
2020 try 2309// RETURN_AT_EDGE is set.
2021 { 2310// if (grp.RootPart.DIE_AT_EDGE)
2022 scene.DeleteSceneObject(grp, false); 2311// {
2023 } 2312// // We remove the object here
2024 catch (Exception) 2313// try
2025 { 2314// {
2026 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); 2315// scene.DeleteSceneObject(grp, false);
2027 } 2316// }
2028 return; 2317// catch (Exception)
2029 } 2318// {
2319// m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
2320// }
2321// return;
2322// }
2030 2323
2031 int thisx = (int)scene.RegionInfo.RegionLocX; 2324 int thisx = (int)scene.RegionInfo.RegionLocX;
2032 int thisy = (int)scene.RegionInfo.RegionLocY; 2325 int thisy = (int)scene.RegionInfo.RegionLocY;
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index d372c0e..7abdc21 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 54
55 private int m_levelHGTeleport = 0; 55 private int m_levelHGTeleport = 0;
56 private string m_ThisHomeURI;
56 57
57 private GatekeeperServiceConnector m_GatekeeperConnector; 58 private GatekeeperServiceConnector m_GatekeeperConnector;
59 private IUserAgentService m_UAS;
58 60
59 protected bool m_RestrictAppearanceAbroad; 61 protected bool m_RestrictAppearanceAbroad;
60 protected string m_AccountName; 62 protected string m_AccountName;
@@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
143 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 145 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
144 } 146 }
145 } 147 }
148
149 moduleConfig = source.Configs["Hypergrid"];
150 if (moduleConfig != null)
151 {
152 m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty);
153 if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/"))
154 m_ThisHomeURI += '/';
155 }
146 } 156 }
147 157
148 public override void AddRegion(Scene scene) 158 public override void AddRegion(Scene scene)
@@ -161,22 +171,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
161 if (!so.IsAttachment) 171 if (!so.IsAttachment)
162 return; 172 return;
163 173
164 if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) 174 if (so.AttachedAvatar == UUID.Zero || Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar))
165 return; 175 return;
166 176
167 // foreign user 177 // foreign user
168 AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); 178 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar);
169 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 179 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
170 { 180 {
171 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 181 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
172 { 182 {
173 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
174 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {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);
175 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 185 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
176 HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); 186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
177 uuidGatherer.GatherAssetUuids(so, ids); 187 uuidGatherer.GatherAssetUuids(so, ids);
178 188
179 foreach (KeyValuePair<UUID, AssetType> kvp in ids) 189 foreach (KeyValuePair<UUID, sbyte> kvp in ids)
180 uuidGatherer.FetchAsset(kvp.Key); 190 uuidGatherer.FetchAsset(kvp.Key);
181 } 191 }
182 } 192 }
@@ -194,7 +204,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
194 base.RegionLoaded(scene); 204 base.RegionLoaded(scene);
195 205
196 if (m_Enabled) 206 if (m_Enabled)
207 {
197 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); 208 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
209 m_UAS = scene.RequestModuleInterface<IUserAgentService>();
210 if (m_UAS == null)
211 m_UAS = new UserAgentServiceConnector(m_ThisHomeURI);
212
213 }
198 } 214 }
199 215
200 public override void RemoveRegion(Scene scene) 216 public override void RemoveRegion(Scene scene)
@@ -272,8 +288,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
272 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) 288 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
273 { 289 {
274 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); 290 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
275 IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); 291 IUserAgentService connector;
276 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); 292
293 if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null)
294 connector = m_UAS;
295 else
296 connector = new UserAgentServiceConnector(userAgentDriver);
297
298 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason);
277 logout = success; // flag for later logout from this grid; this is an HG TP 299 logout = success; // flag for later logout from this grid; this is an HG TP
278 300
279 if (success) 301 if (success)
@@ -552,12 +574,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
552 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId)) 574 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
553 { 575 {
554 // local grid user 576 // local grid user
577 m_UAS.LogoutAgent(obj.AgentId, obj.SessionId);
555 return; 578 return;
556 } 579 }
557 580
558 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode); 581 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
559 582 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("HomeURI"))
560 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
561 { 583 {
562 string url = aCircuit.ServiceURLs["HomeURI"].ToString(); 584 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
563 IUserAgentService security = new UserAgentServiceConnector(url); 585 IUserAgentService security = new UserAgentServiceConnector(url);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index 7871eda..d4fb1ba 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -73,6 +73,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
73 73
74 private AssetMetadata FetchMetadata(string url, UUID assetID) 74 private AssetMetadata FetchMetadata(string url, UUID assetID)
75 { 75 {
76 if (string.IsNullOrEmpty(url))
77 return null;
78
76 if (!url.EndsWith("/") && !url.EndsWith("=")) 79 if (!url.EndsWith("/") && !url.EndsWith("="))
77 url = url + "/"; 80 url = url + "/";
78 81
@@ -92,6 +95,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 95 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
93 if (asset == null) 96 if (asset == null)
94 { 97 {
98 if (string.IsNullOrEmpty(url))
99 return null;
100
95 if (!url.EndsWith("/") && !url.EndsWith("=")) 101 if (!url.EndsWith("/") && !url.EndsWith("="))
96 url = url + "/"; 102 url = url + "/";
97 103
@@ -109,6 +115,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
109 115
110 public bool PostAsset(string url, AssetBase asset) 116 public bool PostAsset(string url, AssetBase asset)
111 { 117 {
118 if (string.IsNullOrEmpty(url))
119 return false;
120
112 if (asset != null) 121 if (asset != null)
113 { 122 {
114 if (!url.EndsWith("/") && !url.EndsWith("=")) 123 if (!url.EndsWith("/") && !url.EndsWith("="))
@@ -165,7 +174,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
165 174
166 private void AdjustIdentifiers(AssetMetadata meta) 175 private void AdjustIdentifiers(AssetMetadata meta)
167 { 176 {
168 if (meta.CreatorID != null && meta.CreatorID != string.Empty) 177 if (!string.IsNullOrEmpty(meta.CreatorID))
169 { 178 {
170 UUID uuid = UUID.Zero; 179 UUID uuid = UUID.Zero;
171 UUID.TryParse(meta.CreatorID, out uuid); 180 UUID.TryParse(meta.CreatorID, out uuid);
@@ -251,9 +260,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
251 260
252 // 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
253 // but not all... 262 // but not all...
254 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 263 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
255 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); 264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
256 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); 265 uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
257 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);
258 bool success = true; 267 bool success = true;
259 foreach (UUID uuid in ids.Keys) 268 foreach (UUID uuid in ids.Keys)
@@ -277,9 +286,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
277 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
278 if (asset != null) 287 if (asset != null)
279 { 288 {
280 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 289 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
281 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
282 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 291 uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
283 bool success = false; 292 bool success = false;
284 foreach (UUID uuid in ids.Keys) 293 foreach (UUID uuid in ids.Keys)
285 { 294 {
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index b2b628d..ce7ed26 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
62 private string m_ThisGatekeeper; 62 private string m_ThisGatekeeper;
63 private bool m_RestrictInventoryAccessAbroad; 63 private bool m_RestrictInventoryAccessAbroad;
64 64
65 private bool m_bypassPermissions = true;
66
65// private bool m_Initialized = false; 67// private bool m_Initialized = false;
66 68
67 #region INonSharedRegionModule 69 #region INonSharedRegionModule
@@ -100,6 +102,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
100 } 102 }
101 else 103 else
102 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 104 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
105
106 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions",
107 new string[] { "Startup", "Permissions" }, true);
108
103 } 109 }
104 } 110 }
105 } 111 }
@@ -114,6 +120,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
114 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem; 120 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
115 scene.EventManager.OnTeleportStart += TeleportStart; 121 scene.EventManager.OnTeleportStart += TeleportStart;
116 scene.EventManager.OnTeleportFail += TeleportFail; 122 scene.EventManager.OnTeleportFail += TeleportFail;
123
124 // We're fgoing to enforce some stricter permissions if Outbound is false
125 scene.Permissions.OnTakeObject += CanTakeObject;
126 scene.Permissions.OnTakeCopyObject += CanTakeObject;
127 scene.Permissions.OnTransferUserInventory += OnTransferUserInventory;
117 } 128 }
118 129
119 #endregion 130 #endregion
@@ -135,7 +146,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
135 if (sp is ScenePresence) 146 if (sp is ScenePresence)
136 { 147 {
137 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); 148 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
138 if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 149 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
139 { 150 {
140 if (m_RestrictInventoryAccessAbroad) 151 if (m_RestrictInventoryAccessAbroad)
141 { 152 {
@@ -185,8 +196,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
185 } 196 }
186 } 197 }
187 198
188 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) 199 public void UploadInventoryItem(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel)
189 { 200 {
201 if (type == AssetType.Link)
202 return;
203
190 string userAssetServer = string.Empty; 204 string userAssetServer = string.Empty;
191 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) 205 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
192 { 206 {
@@ -221,7 +235,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
221 { 235 {
222 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data); 236 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
223 237
224 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0); 238 UploadInventoryItem(remoteClient.AgentId, AssetType.Unknown, newAssetID, "", 0);
225 239
226 return newAssetID; 240 return newAssetID;
227 } 241 }
@@ -232,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
232 protected override void ExportAsset(UUID agentID, UUID assetID) 246 protected override void ExportAsset(UUID agentID, UUID assetID)
233 { 247 {
234 if (!assetID.Equals(UUID.Zero)) 248 if (!assetID.Equals(UUID.Zero))
235 UploadInventoryItem(agentID, assetID, "", 0); 249 UploadInventoryItem(agentID, AssetType.Unknown, assetID, "", 0);
236 else 250 else
237 m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); 251 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
238 } 252 }
@@ -244,7 +258,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
244 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 258 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
245 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 259 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
246 { 260 {
247 m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); 261 m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
248 262
249 //if (fromTaskID.Equals(UUID.Zero)) 263 //if (fromTaskID.Equals(UUID.Zero))
250 //{ 264 //{
@@ -297,7 +311,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
297 if (m_Scene.TryGetScenePresence(userID, out sp)) 311 if (m_Scene.TryGetScenePresence(userID, out sp))
298 { 312 {
299 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 313 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
300 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 314 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
301 { 315 {
302 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 316 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
303 assetServerURL = assetServerURL.Trim(new char[] { '/' }); 317 assetServerURL = assetServerURL.Trim(new char[] { '/' });
@@ -348,7 +362,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
348 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); 362 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId);
349 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); 363 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
350 364
351 inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); 365 List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
366
367 foreach (InventoryFolderBase f in content.Folders)
368 {
369 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
370 keep.Add(f);
371 }
372
373 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
352 } 374 }
353 } 375 }
354 } 376 }
@@ -381,7 +403,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
381 403
382 foreach (InventoryFolderBase f in content.Folders) 404 foreach (InventoryFolderBase f in content.Folders)
383 { 405 {
384 if (f.Name != "My Suitcase") 406 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
385 { 407 {
386 f.Name = f.Name + " (Unavailable)"; 408 f.Name = f.Name + " (Unavailable)";
387 keep.Add(f); 409 keep.Add(f);
@@ -406,5 +428,36 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
406 } 428 }
407 429
408 #endregion 430 #endregion
431
432 #region Permissions
433
434 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene)
435 {
436 if (m_bypassPermissions) return true;
437
438 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer))
439 {
440 SceneObjectGroup sog = null;
441 if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer)
442 return true;
443
444 return false;
445 }
446
447 return true;
448 }
449
450 private bool OnTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
451 {
452 if (m_bypassPermissions) return true;
453
454 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(recipientID))
455 return false;
456
457 return true;
458 }
459
460
461 #endregion
409 } 462 }
410} \ No newline at end of file 463} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 193a27b..7b13e0b 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -390,15 +390,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
390 // Restore attachment data after trip through the sim 390 // Restore attachment data after trip through the sim
391 if (objectGroup.RootPart.AttachPoint > 0) 391 if (objectGroup.RootPart.AttachPoint > 0)
392 { 392 {
393 inventoryStoredPosition = objectGroup.RootPart.AttachOffset; 393 inventoryStoredPosition = objectGroup.RootPart.AttachedPos;
394 inventoryStoredRotation = objectGroup.RootPart.AttachRotation; 394 inventoryStoredRotation = objectGroup.RootPart.AttachRotation;
395 } 395 }
396 396
397 // Trees could be attached and it's been done, but it makes 397 // Trees could be attached and it's been done, but it makes
398 // no sense. State must be preserved because it's the tree type 398 // no sense. State must be preserved because it's the tree type
399 if (objectGroup.RootPart.Shape.PCode != (byte)PCode.Tree && 399 if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
400 objectGroup.RootPart.Shape.PCode != (byte)PCode.NewTree) 400 objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
401 {
401 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; 402 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
403 if (objectGroup.RootPart.AttachPoint > 0)
404 objectGroup.RootPart.Shape.LastAttachPoint = objectGroup.RootPart.AttachPoint;
405 }
402 406
403 objectGroup.AbsolutePosition = inventoryStoredPosition; 407 objectGroup.AbsolutePosition = inventoryStoredPosition;
404 objectGroup.RootPart.RotationOffset = inventoryStoredRotation; 408 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
@@ -446,17 +450,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
446 450
447 if (item == null) 451 if (item == null)
448 return null; 452 return null;
453
454 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
455 item.CreatorData = objlist[0].RootPart.CreatorData;
449 456
450 // Can't know creator is the same, so null it in inventory
451 if (objlist.Count > 1) 457 if (objlist.Count > 1)
452 { 458 {
453 item.CreatorId = UUID.Zero.ToString();
454 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; 459 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
460
461 // If the objects have different creators then don't specify a creator at all
462 foreach (SceneObjectGroup objectGroup in objlist)
463 {
464 if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId)
465 || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData))
466 {
467 item.CreatorId = UUID.Zero.ToString();
468 item.CreatorData = string.Empty;
469 break;
470 }
471 }
455 } 472 }
456 else 473 else
457 { 474 {
458 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
459 item.CreatorData = objlist[0].RootPart.CreatorData;
460 item.SaleType = objlist[0].RootPart.ObjectSaleType; 475 item.SaleType = objlist[0].RootPart.ObjectSaleType;
461 item.SalePrice = objlist[0].RootPart.SalePrice; 476 item.SalePrice = objlist[0].RootPart.SalePrice;
462 } 477 }
@@ -477,13 +492,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
477 } 492 }
478 else 493 else
479 { 494 {
480 AddPermissions(item, objlist[0], objlist, remoteClient);
481
482 item.CreationDate = Util.UnixTimeSinceEpoch(); 495 item.CreationDate = Util.UnixTimeSinceEpoch();
483 item.Description = asset.Description; 496 item.Description = asset.Description;
484 item.Name = asset.Name; 497 item.Name = asset.Name;
485 item.AssetType = asset.Type; 498 item.AssetType = asset.Type;
486 499
500 AddPermissions(item, objlist[0], objlist, remoteClient);
501
487 m_Scene.AddInventoryItem(item); 502 m_Scene.AddInventoryItem(item);
488 503
489 if (remoteClient != null && item.Owner == remoteClient.AgentId) 504 if (remoteClient != null && item.Owner == remoteClient.AgentId)
@@ -538,16 +553,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
538 } 553 }
539 effectivePerms |= (uint)PermissionMask.Move; 554 effectivePerms |= (uint)PermissionMask.Move;
540 555
556 //PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
557
541 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 558 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
542 { 559 {
543 uint perms = effectivePerms; 560 uint perms = effectivePerms;
544 uint nextPerms = (perms & 7) << 13; 561 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms);
545 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
546 perms &= ~(uint)PermissionMask.Copy;
547 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
548 perms &= ~(uint)PermissionMask.Transfer;
549 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
550 perms &= ~(uint)PermissionMask.Modify;
551 562
552 item.BasePermissions = perms & so.RootPart.NextOwnerMask; 563 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
553 item.CurrentPermissions = item.BasePermissions; 564 item.CurrentPermissions = item.BasePermissions;
@@ -555,10 +566,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
555 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask; 566 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
556 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask; 567 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
557 568
558 // Magic number badness. Maybe this deserves an enum. 569 // apply next owner perms on rez
559 // bit 4 (16) is the "Slam" bit, it means treat as passed 570 item.CurrentPermissions |= SceneObjectGroup.SLAM;
560 // and apply next owner perms on rez
561 item.CurrentPermissions |= 16; // Slam!
562 } 571 }
563 else 572 else
564 { 573 {
@@ -575,8 +584,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
575 (uint)PermissionMask.Move | 584 (uint)PermissionMask.Move |
576 (uint)PermissionMask.Export | 585 (uint)PermissionMask.Export |
577 7); // Preserve folded permissions 586 7); // Preserve folded permissions
578 } 587 }
579 588
589 //PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
590
580 return item; 591 return item;
581 } 592 }
582 593
@@ -718,6 +729,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
718 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 729 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
719 if (f != null) 730 if (f != null)
720 folder = m_Scene.InventoryService.GetFolder(f); 731 folder = m_Scene.InventoryService.GetFolder(f);
732
733 if(folder.Type == 14 || folder.Type == 16)
734 {
735 // folder.Type = 6;
736 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
737 }
721 } 738 }
722 } 739 }
723 740
@@ -790,83 +807,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
790 807
791 SceneObjectGroup group = null; 808 SceneObjectGroup group = null;
792 809
793 string xmlData = Utils.BytesToString(rezAsset.Data); 810 List<SceneObjectGroup> objlist;
794 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); 811 List<Vector3> veclist;
795 List<Vector3> veclist = new List<Vector3>(); 812 Vector3 bbox;
813 float offsetHeight;
796 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 814 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
797 Vector3 pos; 815 Vector3 pos;
798 816
799 XmlDocument doc = new XmlDocument(); 817 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
800 doc.LoadXml(xmlData);
801 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
802 Vector3 rez_pos;
803 if (e == null || attachment) // Single
804 {
805 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
806 if (!attachment)
807 {
808 g.RootPart.AttachPoint = g.RootPart.Shape.State;
809 g.RootPart.AttachOffset = g.AbsolutePosition;
810 g.RootPart.AttachRotation = g.GroupRotation;
811 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
812 g.RootPart.Shape.PCode != (byte)PCode.Tree)
813 g.RootPart.Shape.State = 0;
814 }
815
816 objlist.Add(g);
817 veclist.Add(new Vector3(0, 0, 0));
818 818
819 float offsetHeight = 0; 819 if (single)
820 {
820 pos = m_Scene.GetNewRezLocation( 821 pos = m_Scene.GetNewRezLocation(
821 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 822 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
822 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 823 BypassRayCast, bRayEndIsIntersection, true, bbox, false);
823 pos.Z += offsetHeight; 824 pos.Z += offsetHeight;
824 rez_pos = pos;
825 } 825 }
826 else 826 else
827 { 827 {
828 XmlElement coll = (XmlElement)e;
829 float bx = Convert.ToSingle(coll.GetAttribute("x"));
830 float by = Convert.ToSingle(coll.GetAttribute("y"));
831 float bz = Convert.ToSingle(coll.GetAttribute("z"));
832 Vector3 bbox = new Vector3(bx, by, bz);
833
834 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, 828 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
835 RayTargetID, Quaternion.Identity, 829 RayTargetID, Quaternion.Identity,
836 BypassRayCast, bRayEndIsIntersection, true, 830 BypassRayCast, bRayEndIsIntersection, true,
837 bbox, false); 831 bbox, false);
838
839 rez_pos = pos;
840
841 pos -= bbox / 2; 832 pos -= bbox / 2;
842
843 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
844 foreach (XmlNode n in groups)
845 {
846 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
847 g.RootPart.AttachPoint = g.RootPart.Shape.State;
848 g.RootPart.AttachOffset = g.AbsolutePosition;
849 g.RootPart.AttachRotation = g.GroupRotation;
850 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
851 g.RootPart.Shape.PCode != (byte)PCode.Tree)
852 g.RootPart.Shape.State = 0;
853
854 objlist.Add(g);
855 XmlElement el = (XmlElement)n;
856
857 string rawX = el.GetAttribute("offsetx");
858 string rawY = el.GetAttribute("offsety");
859 string rawZ = el.GetAttribute("offsetz");
860//
861// m_log.DebugFormat(
862// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
863// g.Name, rawX, rawY, rawZ);
864
865 float x = Convert.ToSingle(rawX);
866 float y = Convert.ToSingle(rawY);
867 float z = Convert.ToSingle(rawZ);
868 veclist.Add(new Vector3(x, y, z));
869 }
870 } 833 }
871 834
872 int primcount = 0; 835 int primcount = 0;
@@ -874,7 +837,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
874 primcount += g.PrimCount; 837 primcount += g.PrimCount;
875 838
876 if (!m_Scene.Permissions.CanRezObject( 839 if (!m_Scene.Permissions.CanRezObject(
877 primcount, remoteClient.AgentId, rez_pos) 840 primcount, remoteClient.AgentId, pos)
878 && !attachment) 841 && !attachment)
879 { 842 {
880 // The client operates in no fail mode. It will 843 // The client operates in no fail mode. It will
@@ -891,7 +854,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
891 return null; 854 return null;
892 } 855 }
893 856
894 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, rez_pos, attachment)) 857 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
895 return null; 858 return null;
896 859
897 for (int i = 0; i < objlist.Count; i++) 860 for (int i = 0; i < objlist.Count; i++)
@@ -911,11 +874,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
911 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); 874 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
912 } 875 }
913 876
914 foreach (SceneObjectPart part in group.Parts) 877 // if this was previously an attachment and is now being rezzed,
878 // save the old attachment info.
879 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
915 { 880 {
916 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. 881 group.RootPart.AttachedPos = group.AbsolutePosition;
917 part.LastOwnerID = part.OwnerID; 882 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
918 part.OwnerID = remoteClient.AgentId; 883 }
884
885 if (item == null)
886 {
887 // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here.
888 foreach (SceneObjectPart part in group.Parts)
889 {
890 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
891 part.LastOwnerID = part.OwnerID;
892 part.OwnerID = remoteClient.AgentId;
893 }
919 } 894 }
920 895
921 if (!attachment) 896 if (!attachment)
@@ -990,10 +965,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
990 /// <param name="item"></param> 965 /// <param name="item"></param>
991 /// <param name="objlist"></param> 966 /// <param name="objlist"></param>
992 /// <param name="pos"></param> 967 /// <param name="pos"></param>
968 /// <param name="veclist">
969 /// List of vector position adjustments for a coalesced objects. For ordinary objects
970 /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
971 /// </param>
993 /// <param name="isAttachment"></param> 972 /// <param name="isAttachment"></param>
994 /// <returns>true if we can processed with rezzing, false if we need to abort</returns> 973 /// <returns>true if we can processed with rezzing, false if we need to abort</returns>
995 private bool DoPreRezWhenFromItem( 974 private bool DoPreRezWhenFromItem(
996 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment) 975 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
976 Vector3 pos, List<Vector3> veclist, bool isAttachment)
997 { 977 {
998 UUID fromUserInventoryItemId = UUID.Zero; 978 UUID fromUserInventoryItemId = UUID.Zero;
999 979
@@ -1016,28 +996,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1016 } 996 }
1017 } 997 }
1018 998
1019 int primcount = 0; 999 for (int i = 0; i < objlist.Count; i++)
1020 foreach (SceneObjectGroup g in objlist)
1021 primcount += g.PrimCount;
1022
1023 if (!m_Scene.Permissions.CanRezObject(
1024 primcount, remoteClient.AgentId, pos)
1025 && !isAttachment)
1026 { 1000 {
1027 // The client operates in no fail mode. It will 1001 SceneObjectGroup g = objlist[i];
1028 // have already removed the item from the folder 1002
1029 // if it's no copy. 1003 if (!m_Scene.Permissions.CanRezObject(
1030 // Put it back if it's not an attachment 1004 g.PrimCount, remoteClient.AgentId, pos + veclist[i])
1031 // 1005 && !isAttachment)
1032 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) 1006 {
1033 remoteClient.SendBulkUpdateInventory(item); 1007 // The client operates in no fail mode. It will
1008 // have already removed the item from the folder
1009 // if it's no copy.
1010 // Put it back if it's not an attachment
1011 //
1012 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
1013 remoteClient.SendBulkUpdateInventory(item);
1034 1014
1035 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 1015 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
1036 remoteClient.SendAlertMessage(string.Format( 1016 remoteClient.SendAlertMessage(string.Format(
1037 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", 1017 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
1038 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName)); 1018 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
1039 1019
1040 return false; 1020 return false;
1021 }
1041 } 1022 }
1042 1023
1043 for (int i = 0; i < objlist.Count; i++) 1024 for (int i = 0; i < objlist.Count; i++)
@@ -1051,15 +1032,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1051 // object itself before we rez. 1032 // object itself before we rez.
1052 // 1033 //
1053 // Only do these for the first object if we are rezzing a coalescence. 1034 // Only do these for the first object if we are rezzing a coalescence.
1054 if (i == 0) 1035 // nahh dont mess with coalescence objects,
1036 // the name in inventory can be change for inventory purpuses only
1037 if (objlist.Count == 1)
1055 { 1038 {
1056 rootPart.Name = item.Name; 1039 rootPart.Name = item.Name;
1057 rootPart.Description = item.Description; 1040 rootPart.Description = item.Description;
1058 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0) 1041 }
1059 { 1042
1060 rootPart.ObjectSaleType = item.SaleType; 1043 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
1061 rootPart.SalePrice = item.SalePrice; 1044 {
1062 } 1045 rootPart.ObjectSaleType = item.SaleType;
1046 rootPart.SalePrice = item.SalePrice;
1063 } 1047 }
1064 1048
1065 so.FromFolderID = item.Folder; 1049 so.FromFolderID = item.Folder;
@@ -1118,7 +1102,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1118 part.GroupMask = item.GroupPermissions; 1102 part.GroupMask = item.GroupPermissions;
1119 } 1103 }
1120 } 1104 }
1121 1105
1122 rootPart.TrimPermissions(); 1106 rootPart.TrimPermissions();
1123 1107
1124 if (isAttachment) 1108 if (isAttachment)
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index d07cff4..69d7e16 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
176 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName); 176 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName);
177 simpleName = GetInventoryPathFromName(simpleName); 177 simpleName = GetInventoryPathFromName(simpleName);
178 178
179 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName, false); 179 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, simpleName, iarFileName, false);
180 try 180 try
181 { 181 {
182 HashSet<InventoryNodeBase> nodes = archread.Execute(); 182 HashSet<InventoryNodeBase> nodes = archread.Execute();
@@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
185 // didn't find the subfolder with the given name; place it on the top 185 // didn't find the subfolder with the given name; place it on the top
186 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName); 186 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName);
187 archread.Close(); 187 archread.Close();
188 archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName, false); 188 archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, "/", iarFileName, false);
189 archread.Execute(); 189 archread.Execute();
190 } 190 }
191 191
diff --git a/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
new file mode 100644
index 0000000..8838612
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
@@ -0,0 +1,197 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.IO;
30using System.Reflection;
31using System.Threading;
32
33using OpenSim.Framework;
34using OpenSim.Framework.Console;
35using OpenSim.Framework.Monitoring;
36using OpenSim.Region.ClientStack.LindenUDP;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Hypergrid;
42
43using OpenMetaverse;
44using OpenMetaverse.Packets;
45using log4net;
46using Nini.Config;
47using Mono.Addins;
48
49using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
50
51namespace OpenSim.Region.CoreModules.Framework.Search
52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicSearchModule")]
54 public class BasicSearchModule : ISharedRegionModule
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 protected bool m_Enabled;
59 protected List<Scene> m_Scenes = new List<Scene>();
60
61 private IGroupsModule m_GroupsService = null;
62
63 #region ISharedRegionModule
64
65 public void Initialise(IConfigSource config)
66 {
67 string umanmod = config.Configs["Modules"].GetString("SearchModule", Name);
68 if (umanmod == Name)
69 {
70 m_Enabled = true;
71 m_log.DebugFormat("[BASIC SEARCH MODULE]: {0} is enabled", Name);
72 }
73 }
74
75 public bool IsSharedModule
76 {
77 get { return true; }
78 }
79
80 public virtual string Name
81 {
82 get { return "BasicSearchModule"; }
83 }
84
85 public Type ReplaceableInterface
86 {
87 get { return null; }
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (m_Enabled)
93 {
94 m_Scenes.Add(scene);
95
96 scene.EventManager.OnMakeRootAgent += new Action<ScenePresence>(EventManager_OnMakeRootAgent);
97 scene.EventManager.OnMakeChildAgent += new EventManager.OnMakeChildAgentDelegate(EventManager_OnMakeChildAgent);
98 }
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103 if (m_Enabled)
104 {
105 m_Scenes.Remove(scene);
106
107 scene.EventManager.OnMakeRootAgent -= new Action<ScenePresence>(EventManager_OnMakeRootAgent);
108 scene.EventManager.OnMakeChildAgent -= new EventManager.OnMakeChildAgentDelegate(EventManager_OnMakeChildAgent);
109 }
110 }
111
112 public void RegionLoaded(Scene s)
113 {
114 if (!m_Enabled)
115 return;
116
117 if (m_GroupsService == null)
118 {
119 m_GroupsService = s.RequestModuleInterface<IGroupsModule>();
120
121 // No Groups Service Connector, then group search won't work...
122 if (m_GroupsService == null)
123 m_log.Warn("[BASIC SEARCH MODULE]: Could not get IGroupsModule");
124 }
125 }
126
127 public void PostInitialise()
128 {
129 }
130
131 public void Close()
132 {
133 m_Scenes.Clear();
134 }
135
136 #endregion ISharedRegionModule
137
138
139 #region Event Handlers
140
141 void EventManager_OnMakeRootAgent(ScenePresence sp)
142 {
143 sp.ControllingClient.OnDirFindQuery += OnDirFindQuery;
144 }
145
146 void EventManager_OnMakeChildAgent(ScenePresence sp)
147 {
148 sp.ControllingClient.OnDirFindQuery -= OnDirFindQuery;
149 }
150
151 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
152 {
153 if (((DirFindFlags)queryFlags & DirFindFlags.People) == DirFindFlags.People)
154 {
155 if (string.IsNullOrEmpty(queryText))
156 remoteClient.SendDirPeopleReply(queryID, new DirPeopleReplyData[0]);
157
158 List<UserAccount> accounts = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, queryText);
159 DirPeopleReplyData[] hits = new DirPeopleReplyData[accounts.Count];
160 int i = 0;
161 foreach (UserAccount acc in accounts)
162 {
163 DirPeopleReplyData d = new DirPeopleReplyData();
164 d.agentID = acc.PrincipalID;
165 d.firstName = acc.FirstName;
166 d.lastName = acc.LastName;
167 d.online = false;
168
169 hits[i++] = d;
170 }
171
172 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
173 remoteClient.SendDirPeopleReply(queryID, hits);
174 }
175 else if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
176 {
177 if (m_GroupsService == null)
178 {
179 m_log.Warn("[BASIC SEARCH MODULE]: Groups service is not available. Unable to search groups.");
180 remoteClient.SendAlertMessage("Groups search is not enabled");
181 return;
182 }
183
184 if (string.IsNullOrEmpty(queryText))
185 remoteClient.SendDirGroupsReply(queryID, new DirGroupsReplyData[0]);
186
187 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
188 remoteClient.SendDirGroupsReply(queryID, m_GroupsService.FindGroups(remoteClient, queryText).ToArray());
189 }
190
191 }
192
193 #endregion Event Handlers
194
195 }
196
197} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
new file mode 100644
index 0000000..a70261e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
@@ -0,0 +1,256 @@
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.Reflection;
31using System.Threading;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Framework.Monitoring;
39using OpenSim.Region.Framework.Scenes;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41
42namespace OpenSim.Region.CoreModules.Framework
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
45 public class ServiceThrottleModule : ISharedRegionModule, IServiceThrottleModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private readonly List<Scene> m_scenes = new List<Scene>();
51 private System.Timers.Timer m_timer = new System.Timers.Timer();
52
53 private Queue<Action> m_RequestQueue = new Queue<Action>();
54 private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55 private int m_Interval;
56
57 #region ISharedRegionModule
58
59 public void Initialise(IConfigSource config)
60 {
61 m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
62
63 m_timer = new System.Timers.Timer();
64 m_timer.AutoReset = false;
65 m_timer.Enabled = true;
66 m_timer.Interval = 15000; // 15 secs at first
67 m_timer.Elapsed += ProcessQueue;
68 m_timer.Start();
69
70 //Watchdog.StartThread(
71 // ProcessQueue,
72 // "GridServiceRequestThread",
73 // ThreadPriority.BelowNormal,
74 // true,
75 // false);
76 }
77
78 public void AddRegion(Scene scene)
79 {
80 lock (m_scenes)
81 {
82 m_scenes.Add(scene);
83 scene.RegisterModuleInterface<IServiceThrottleModule>(this);
84 scene.EventManager.OnNewClient += OnNewClient;
85 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
86 }
87 }
88
89 public void RegionLoaded(Scene scene)
90 {
91 }
92
93 public void RemoveRegion(Scene scene)
94 {
95 lock (m_scenes)
96 {
97 m_scenes.Remove(scene);
98 scene.EventManager.OnNewClient -= OnNewClient;
99 }
100 }
101
102 public void PostInitialise()
103 {
104 }
105
106 public void Close()
107 {
108 }
109
110 public string Name
111 {
112 get { return "ServiceThrottleModule"; }
113 }
114
115 public Type ReplaceableInterface
116 {
117 get { return null; }
118 }
119
120 #endregion ISharedRegionMOdule
121
122 #region Events
123
124 void OnNewClient(IClientAPI client)
125 {
126 client.OnRegionHandleRequest += OnRegionHandleRequest;
127 }
128
129 void OnMakeRootAgent(ScenePresence obj)
130 {
131 lock (m_timer)
132 {
133 if (!m_timer.Enabled)
134 {
135 m_timer.Interval = m_Interval;
136 m_timer.Enabled = true;
137 m_timer.Start();
138 }
139 }
140 }
141
142 public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
143 {
144 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
145 ulong handle = 0;
146 if (IsLocalRegionHandle(regionID, out handle))
147 {
148 client.SendRegionHandle(regionID, handle);
149 return;
150 }
151
152 Action action = delegate
153 {
154 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
155
156 if (r != null && r.RegionHandle != 0)
157 client.SendRegionHandle(regionID, r.RegionHandle);
158 };
159
160 Enqueue("region", regionID.ToString(), action);
161 }
162
163 #endregion Events
164
165 #region IServiceThrottleModule
166
167 public void Enqueue(string category, string itemid, Action continuation)
168 {
169 lock (m_RequestQueue)
170 {
171 if (m_Pending.ContainsKey(category))
172 {
173 if (m_Pending[category].Contains(itemid))
174 // Don't enqueue, it's already pending
175 return;
176 }
177 else
178 m_Pending.Add(category, new List<string>());
179
180 m_Pending[category].Add(itemid);
181
182 m_RequestQueue.Enqueue(delegate
183 {
184 lock (m_RequestQueue)
185 m_Pending[category].Remove(itemid);
186
187 continuation();
188 });
189 }
190 }
191
192 #endregion IServiceThrottleModule
193
194 #region Process Continuation Queue
195
196 private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197 {
198 //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199
200 while (m_RequestQueue.Count > 0)
201 {
202 Action continuation = null;
203 lock (m_RequestQueue)
204 continuation = m_RequestQueue.Dequeue();
205
206 if (continuation != null)
207 continuation();
208 }
209
210 if (AreThereRootAgents())
211 {
212 lock (m_timer)
213 {
214 m_timer.Interval = 1000; // 1 sec
215 m_timer.Enabled = true;
216 m_timer.Start();
217 }
218 }
219 else
220 lock (m_timer)
221 m_timer.Enabled = false;
222
223 }
224
225 #endregion Process Continuation Queue
226
227 #region Misc
228
229 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
230 {
231 regionHandle = 0;
232 foreach (Scene s in m_scenes)
233 if (s.RegionInfo.RegionID == regionID)
234 {
235 regionHandle = s.RegionInfo.RegionHandle;
236 return true;
237 }
238 return false;
239 }
240
241 private bool AreThereRootAgents()
242 {
243 foreach (Scene s in m_scenes)
244 {
245 foreach (ScenePresence sp in s.GetScenePresences())
246 if (!sp.IsChildAgent)
247 return true;
248 }
249
250 return false;
251 }
252
253 #endregion Misc
254 }
255
256}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index 4ef57fe..245c808 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -50,16 +50,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53
54 #region ISharedRegionModule 53 #region ISharedRegionModule
55 54
56 public new void Initialise(IConfigSource config) 55 public new void Initialise(IConfigSource config)
57 { 56 {
58 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", base.Name); 57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null);
59 if (umanmod == Name) 58 if (umanmod == Name)
60 { 59 {
61 m_Enabled = true; 60 m_Enabled = true;
62 RegisterConsoleCmds(); 61 Init();
63 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); 62 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
64 } 63 }
65 } 64 }
@@ -71,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
71 70
72 #endregion ISharedRegionModule 71 #endregion ISharedRegionModule
73 72
74 protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) 73 protected override void AddAdditionalUsers(string query, List<UserData> users)
75 { 74 {
76 if (query.Contains("@")) // First.Last@foo.com, maybe? 75 if (query.Contains("@")) // First.Last@foo.com, maybe?
77 { 76 {
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
new file mode 100644
index 0000000..9d36aa5
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
@@ -0,0 +1,76 @@
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 Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.CoreModules.Framework.UserManagement;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.CoreModules.Framework.UserManagement.Tests
38{
39 [TestFixture]
40 public class HGUserManagementModuleTests : OpenSimTestCase
41 {
42 /// <summary>
43 /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation.
44 /// </summary>
45 [Test]
46 public void TestCachedUserNameForNewAgent()
47 {
48 TestHelpers.InMethod();
49// TestHelpers.EnableLogging();
50
51 HGUserManagementModule hgumm = new HGUserManagementModule();
52 UUID userId = TestHelpers.ParseStem("11");
53 string firstName = "Fred";
54 string lastName = "Astaire";
55 string homeUri = "example.com";
56
57 IConfigSource config = new IniConfigSource();
58 config.AddConfig("Modules");
59 config.Configs["Modules"].Set("UserManagementModule", hgumm.Name);
60
61 SceneHelpers sceneHelpers = new SceneHelpers();
62 TestScene scene = sceneHelpers.SetupScene();
63 SceneHelpers.SetupSceneModules(scene, config, hgumm);
64
65 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
66 acd.firstname = firstName;
67 acd.lastname = lastName;
68 acd.ServiceURLs["HomeURI"] = "http://" + homeUri;
69
70 SceneHelpers.AddScenePresence(scene, acd);
71
72 string name = hgumm.GetUserName(userId);
73 Assert.That(name, Is.EqualTo(string.Format("{0}.{1} @{2}", firstName, lastName, homeUri)));
74 }
75 }
76} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 77e8b00..e571c62 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -28,9 +28,11 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Threading;
31 32
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Framework.Console; 34using OpenSim.Framework.Console;
35using OpenSim.Framework.Monitoring;
34using OpenSim.Region.ClientStack.LindenUDP; 36using OpenSim.Region.ClientStack.LindenUDP;
35using OpenSim.Region.Framework; 37using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
@@ -44,25 +46,19 @@ using log4net;
44using Nini.Config; 46using Nini.Config;
45using Mono.Addins; 47using Mono.Addins;
46 48
49using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
50
47namespace OpenSim.Region.CoreModules.Framework.UserManagement 51namespace OpenSim.Region.CoreModules.Framework.UserManagement
48{ 52{
49 public class UserData
50 {
51 public UUID Id { get; set; }
52 public string FirstName { get; set; }
53 public string LastName { get; set; }
54 public string HomeURL { get; set; }
55 public Dictionary<string, object> ServerURLs { get; set; }
56 }
57
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
59 public class UserManagementModule : ISharedRegionModule, IUserManagement 54 public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople
60 { 55 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 57
63 protected bool m_Enabled; 58 protected bool m_Enabled;
64 protected List<Scene> m_Scenes = new List<Scene>(); 59 protected List<Scene> m_Scenes = new List<Scene>();
65 60
61 protected IServiceThrottleModule m_ServiceThrottle;
66 // The cache 62 // The cache
67 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); 63 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
68 64
@@ -74,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
74 if (umanmod == Name) 70 if (umanmod == Name)
75 { 71 {
76 m_Enabled = true; 72 m_Enabled = true;
77 RegisterConsoleCmds(); 73 Init();
78 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); 74 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
79 } 75 }
80 } 76 }
@@ -101,6 +97,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
101 m_Scenes.Add(scene); 97 m_Scenes.Add(scene);
102 98
103 scene.RegisterModuleInterface<IUserManagement>(this); 99 scene.RegisterModuleInterface<IUserManagement>(this);
100 scene.RegisterModuleInterface<IPeople>(this);
104 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); 101 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
105 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); 102 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
106 } 103 }
@@ -117,6 +114,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
117 114
118 public void RegionLoaded(Scene s) 115 public void RegionLoaded(Scene s)
119 { 116 {
117 if (m_Enabled && m_ServiceThrottle == null)
118 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
120 } 119 }
121 120
122 public void PostInitialise() 121 public void PostInitialise()
@@ -143,7 +142,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
143 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); 142 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
144 } 143 }
145 144
146
147 void EventManager_OnNewClient(IClientAPI client) 145 void EventManager_OnNewClient(IClientAPI client)
148 { 146 {
149 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); 147 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed);
@@ -157,21 +155,43 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
157 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); 155 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
158 } 156 }
159 157
160 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 158 void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
161 { 159 {
160// m_log.DebugFormat(
161// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
162// uuid, remote_client.Name);
163
162 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 164 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
163 { 165 {
164 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 166 client.SendNameReply(uuid, "Mr", "OpenSim");
165 } 167 }
166 else 168 else
167 { 169 {
168 string[] names = GetUserNames(uuid); 170 string[] names = new string[2];
169 if (names.Length == 2) 171 if (TryGetUserNamesFromCache(uuid, names))
170 { 172 {
171 //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); 173 client.SendNameReply(uuid, names[0], names[1]);
172 remote_client.SendNameReply(uuid, names[0], names[1]); 174 return;
173 } 175 }
174 176
177 // Not found in cache, queue continuation
178 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
179 {
180 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
181
182 // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients
183 // appear to clear this when the user asks it to clear the cache, but others may not.
184 //
185 // So to avoid clients
186 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
187 // instead drop the request entirely.
188 if (TryGetUserNames(uuid, names))
189 client.SendNameReply(uuid, names[0], names[1]);
190// else
191// m_log.DebugFormat(
192// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
193// uuid, client.Name);
194 });
175 } 195 }
176 } 196 }
177 197
@@ -181,29 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
181 201
182 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); 202 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
183 203
184 // searhc the user accounts service 204 List<UserData> users = GetUserData(query, 500, 1);
185 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
186
187 List<UserData> users = new List<UserData>();
188 if (accs != null)
189 {
190 foreach (UserAccount acc in accs)
191 {
192 UserData ud = new UserData();
193 ud.FirstName = acc.FirstName;
194 ud.LastName = acc.LastName;
195 ud.Id = acc.PrincipalID;
196 users.Add(ud);
197 }
198 }
199
200 // search the local cache
201 foreach (UserData data in m_UserCache.Values)
202 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
203 (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query)))
204 users.Add(data);
205
206 AddAdditionalUsers(avatarID, query, users);
207 205
208 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 206 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
209 // TODO: don't create new blocks if recycling an old packet 207 // TODO: don't create new blocks if recycling an old packet
@@ -249,12 +247,51 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
249 client.SendAvatarPickerReply(agent_data, data_args); 247 client.SendAvatarPickerReply(agent_data, data_args);
250 } 248 }
251 249
252 protected virtual void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) 250 protected virtual void AddAdditionalUsers(string query, List<UserData> users)
253 { 251 {
254 } 252 }
255 253
256 #endregion Event Handlers 254 #endregion Event Handlers
257 255
256 #region IPeople
257
258 public List<UserData> GetUserData(string query, int page_size, int page_number)
259 {
260 // search the user accounts service
261 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
262
263 List<UserData> users = new List<UserData>();
264 if (accs != null)
265 {
266 foreach (UserAccount acc in accs)
267 {
268 UserData ud = new UserData();
269 ud.FirstName = acc.FirstName;
270 ud.LastName = acc.LastName;
271 ud.Id = acc.PrincipalID;
272 users.Add(ud);
273 }
274 }
275
276 // search the local cache
277 lock (m_UserCache)
278 {
279 foreach (UserData data in m_UserCache.Values)
280 {
281 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
282 (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
283 users.Add(data);
284 }
285 }
286
287 AddAdditionalUsers(query, users);
288
289 return users;
290
291 }
292
293 #endregion IPeople
294
258 private void CacheCreators(SceneObjectGroup sog) 295 private void CacheCreators(SceneObjectGroup sog)
259 { 296 {
260 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); 297 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
@@ -268,26 +305,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
268 } 305 }
269 } 306 }
270 307
271 private string[] GetUserNames(UUID uuid) 308 /// <summary>
309 ///
310 /// </summary>
311 /// <param name="uuid"></param>
312 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
313 /// <returns></returns>
314 private bool TryGetUserNames(UUID uuid, string[] names)
272 { 315 {
273 string[] returnstring = new string[2]; 316 if (names == null)
317 names = new string[2];
318
319 if (TryGetUserNamesFromCache(uuid, names))
320 return true;
274 321
322 if (TryGetUserNamesFromServices(uuid, names))
323 return true;
324
325 return false;
326 }
327
328 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
329 {
275 lock (m_UserCache) 330 lock (m_UserCache)
276 { 331 {
277 if (m_UserCache.ContainsKey(uuid)) 332 if (m_UserCache.ContainsKey(uuid))
278 { 333 {
279 returnstring[0] = m_UserCache[uuid].FirstName; 334 names[0] = m_UserCache[uuid].FirstName;
280 returnstring[1] = m_UserCache[uuid].LastName; 335 names[1] = m_UserCache[uuid].LastName;
281 return returnstring; 336
337 return true;
282 } 338 }
283 } 339 }
284 340
341 return false;
342 }
343
344 /// <summary>
345 /// Try to get the names bound to the given uuid, from the services.
346 /// </summary>
347 /// <returns>True if the name was found, false if not.</returns>
348 /// <param name='uuid'></param>
349 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
350 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
351 {
285 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); 352 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
286 353
287 if (account != null) 354 if (account != null)
288 { 355 {
289 returnstring[0] = account.FirstName; 356 names[0] = account.FirstName;
290 returnstring[1] = account.LastName; 357 names[1] = account.LastName;
291 358
292 UserData user = new UserData(); 359 UserData user = new UserData();
293 user.FirstName = account.FirstName; 360 user.FirstName = account.FirstName;
@@ -295,14 +362,42 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
295 362
296 lock (m_UserCache) 363 lock (m_UserCache)
297 m_UserCache[uuid] = user; 364 m_UserCache[uuid] = user;
365
366 return true;
298 } 367 }
299 else 368 else
300 { 369 {
301 returnstring[0] = "Unknown"; 370 // Let's try the GridUser service
302 returnstring[1] = "User"; 371 GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
303 } 372 if (uInfo != null)
373 {
374 string url, first, last, tmp;
375 UUID u;
376 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
377 {
378 AddUser(uuid, first, last, url);
379
380 if (m_UserCache.ContainsKey(uuid))
381 {
382 names[0] = m_UserCache[uuid].FirstName;
383 names[1] = m_UserCache[uuid].LastName;
384
385 return true;
386 }
387 }
388 else
389 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
390 }
391// else
392// {
393// m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
394// }
395
396 names[0] = "Unknown";
397 names[1] = "UserUMMTGUN9";
304 398
305 return returnstring; 399 return false;
400 }
306 } 401 }
307 402
308 #region IUserManagement 403 #region IUserManagement
@@ -338,16 +433,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
338 433
339 public string GetUserName(UUID uuid) 434 public string GetUserName(UUID uuid)
340 { 435 {
341 string[] names = GetUserNames(uuid); 436 string[] names = new string[2];
342 if (names.Length == 2) 437 TryGetUserNames(uuid, names);
343 {
344 string firstname = names[0];
345 string lastname = names[1];
346 438
347 return firstname + " " + lastname; 439 return names[0] + " " + names[1];
348 440
349 }
350 return "(hippos)";
351 } 441 }
352 442
353 public string GetUserHomeURL(UUID userID) 443 public string GetUserHomeURL(UUID userID)
@@ -376,7 +466,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
376 return userdata.ServerURLs[serverType].ToString(); 466 return userdata.ServerURLs[serverType].ToString();
377 } 467 }
378 468
379 if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) 469 if (!string.IsNullOrEmpty(userdata.HomeURL))
380 { 470 {
381 //m_log.DebugFormat( 471 //m_log.DebugFormat(
382 // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}", 472 // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
@@ -394,14 +484,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
394 484
395 public string GetUserUUI(UUID userID) 485 public string GetUserUUI(UUID userID)
396 { 486 {
397 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
398 if (account != null)
399 return userID.ToString();
400
401 UserData ud; 487 UserData ud;
402 lock (m_UserCache) 488 lock (m_UserCache)
403 m_UserCache.TryGetValue(userID, out ud); 489 m_UserCache.TryGetValue(userID, out ud);
404 490
491 if (ud == null) // It's not in the cache
492 {
493 string[] names = new string[2];
494 // This will pull the data from either UserAccounts or GridUser
495 // and stick it into the cache
496 TryGetUserNamesFromServices(userID, names);
497 lock (m_UserCache)
498 m_UserCache.TryGetValue(userID, out ud);
499 }
500
405 if (ud != null) 501 if (ud != null)
406 { 502 {
407 string homeURL = ud.HomeURL; 503 string homeURL = ud.HomeURL;
@@ -446,77 +542,81 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
446 AddUser(uuid, homeURL + ";" + first + " " + last); 542 AddUser(uuid, homeURL + ";" + first + " " + last);
447 } 543 }
448 544
449 public void AddUser (UUID id, string creatorData) 545 public void AddUser(UUID id, string creatorData)
450 { 546 {
451 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); 547 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
452 548
453 UserData oldUser; 549 UserData oldUser;
454 //lock the whole block - prevent concurrent update
455 lock (m_UserCache) 550 lock (m_UserCache)
551 m_UserCache.TryGetValue(id, out oldUser);
552
553 if (oldUser != null)
456 { 554 {
457 m_UserCache.TryGetValue (id, out oldUser); 555 if (string.IsNullOrEmpty(creatorData))
458 if (oldUser != null)
459 { 556 {
460 if (creatorData == null || creatorData == String.Empty) 557 //ignore updates without creator data
461 { 558 return;
462 //ignore updates without creator data
463 return;
464 }
465 //try update unknown users
466 //and creator's home URL's
467 if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL)))
468 {
469 m_UserCache.Remove (id);
470// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL);
471 }
472 else
473 {
474 //we have already a valid user within the cache
475 return;
476 }
477 } 559 }
478 560
479 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id); 561 //try update unknown users, but don't update anyone else
480 562 if (oldUser.FirstName == "Unknown" && !creatorData.Contains("Unknown"))
481 if (account != null)
482 { 563 {
483 AddUser (id, account.FirstName, account.LastName); 564 lock (m_UserCache)
565 m_UserCache.Remove(id);
566 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
484 } 567 }
485 else 568 else
486 { 569 {
487 UserData user = new UserData (); 570 //we have already a valid user within the cache
488 user.Id = id; 571 return;
572 }
573 }
489 574
490 if (creatorData != null && creatorData != string.Empty) 575 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id);
491 {
492 //creatorData = <endpoint>;<name>
493 576
494 string[] parts = creatorData.Split (';'); 577 if (account != null)
495 if (parts.Length >= 1) 578 {
579 AddUser(id, account.FirstName, account.LastName);
580 }
581 else
582 {
583 UserData user = new UserData();
584 user.Id = id;
585
586 if (!string.IsNullOrEmpty(creatorData))
587 {
588 //creatorData = <endpoint>;<name>
589
590 string[] parts = creatorData.Split(';');
591 if (parts.Length >= 1)
592 {
593 user.HomeURL = parts[0];
594 try
496 { 595 {
497 user.HomeURL = parts [0]; 596 Uri uri = new Uri(parts[0]);
498 try 597 user.LastName = "@" + uri.Authority;
499 { 598 }
500 Uri uri = new Uri (parts [0]); 599 catch (UriFormatException)
501 user.LastName = "@" + uri.Authority; 600 {
502 } 601 m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]);
503 catch (UriFormatException) 602 user.LastName = "@unknown";
504 {
505 m_log.DebugFormat ("[SCENE]: Unable to parse Uri {0}", parts [0]);
506 user.LastName = "@unknown";
507 }
508 } 603 }
509 if (parts.Length >= 2)
510 user.FirstName = parts [1].Replace (' ', '.');
511 }
512 else
513 {
514 user.FirstName = "Unknown";
515 user.LastName = "User";
516 } 604 }
517 605
518 AddUserInternal (user); 606 if (parts.Length >= 2)
607 user.FirstName = parts[1].Replace(' ', '.');
608 }
609 else
610 {
611 // Temporarily add unknown user entries of this type into the cache so that we can distinguish
612 // this source from other recent (hopefully resolved) bugs that fail to retrieve a user name binding
613 // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or
614 // disappeared.
615 user.FirstName = "Unknown";
616 user.LastName = "UserUMMAU4";
519 } 617 }
618
619 AddUserInternal(user);
520 } 620 }
521 } 621 }
522 622
@@ -541,9 +641,22 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
541 641
542 #endregion IUserManagement 642 #endregion IUserManagement
543 643
644 protected void Init()
645 {
646 AddUser(UUID.Zero, "Unknown", "User");
647 RegisterConsoleCmds();
648 }
649
544 protected void RegisterConsoleCmds() 650 protected void RegisterConsoleCmds()
545 { 651 {
546 MainConsole.Instance.Commands.AddCommand("Users", true, 652 MainConsole.Instance.Commands.AddCommand("Users", true,
653 "show name",
654 "show name <uuid>",
655 "Show the bindings between a single user UUID and a user name",
656 String.Empty,
657 HandleShowUser);
658
659 MainConsole.Instance.Commands.AddCommand("Users", true,
547 "show names", 660 "show names",
548 "show names", 661 "show names",
549 "Show the bindings between user UUIDs and user names", 662 "Show the bindings between user UUIDs and user names",
@@ -551,26 +664,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
551 HandleShowUsers); 664 HandleShowUsers);
552 } 665 }
553 666
554 private void HandleShowUsers(string module, string[] cmd) 667 private void HandleShowUser(string module, string[] cmd)
555 { 668 {
669 if (cmd.Length < 3)
670 {
671 MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
672 return;
673 }
674
675 UUID userId;
676 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
677 return;
678
679 string[] names;
680
681 UserData ud;
682
556 lock (m_UserCache) 683 lock (m_UserCache)
557 { 684 {
558 if (m_UserCache.Count == 0) 685 if (!m_UserCache.TryGetValue(userId, out ud))
559 { 686 {
560 MainConsole.Instance.Output("No users found"); 687 MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
561 return; 688 return;
562 } 689 }
563 690 }
564 MainConsole.Instance.Output("UUID User Name"); 691
565 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 692 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
693 cdt.AddColumn("UUID", 36);
694 cdt.AddColumn("Name", 30);
695 cdt.AddColumn("HomeURL", 40);
696 cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
697
698 MainConsole.Instance.Output(cdt.ToString());
699 }
700
701 private void HandleShowUsers(string module, string[] cmd)
702 {
703 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
704 cdt.AddColumn("UUID", 36);
705 cdt.AddColumn("Name", 30);
706 cdt.AddColumn("HomeURL", 40);
707
708 lock (m_UserCache)
709 {
566 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 710 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
567 { 711 cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL);
568 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
569 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
570 }
571
572 return;
573 } 712 }
713
714 MainConsole.Instance.Output(cdt.ToString());
574 } 715 }
716
575 } 717 }
576} \ No newline at end of file 718
719}
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index 7b11658..8946b5c 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
34using Mono.Addins; 35using Mono.Addins;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.CoreModules.World.WorldMap; 37using OpenSim.Region.CoreModules.World.WorldMap;
@@ -48,20 +49,63 @@ namespace OpenSim.Region.CoreModules.Hypergrid
48 // Remember the map area that each client has been exposed to in this region 49 // Remember the map area that each client has been exposed to in this region
49 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>(); 50 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>();
50 51
52 private string m_MapImageServerURL = string.Empty;
53
54 private IUserManagement m_UserManagement;
55
51 #region INonSharedRegionModule Members 56 #region INonSharedRegionModule Members
52 57
53 public override void Initialise(IConfigSource config) 58 public override void Initialise(IConfigSource source)
54 { 59 {
55 if (Util.GetConfigVarFromSections<string>( 60 if (Util.GetConfigVarFromSections<string>(
56 config, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap") 61 source, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap")
62 {
57 m_Enabled = true; 63 m_Enabled = true;
64
65 m_MapImageServerURL = Util.GetConfigVarFromSections<string>(source, "MapTileURL", new string[] {"LoginService", "HGWorldMap", "SimulatorFeatures"});
66
67 if (!string.IsNullOrEmpty(m_MapImageServerURL))
68 {
69 m_MapImageServerURL = m_MapImageServerURL.Trim();
70 if (!m_MapImageServerURL.EndsWith("/"))
71 m_MapImageServerURL = m_MapImageServerURL + "/";
72 }
73
74
75 }
58 } 76 }
59 77
60 public override void AddRegion(Scene scene) 78 public override void AddRegion(Scene scene)
61 { 79 {
80 if (!m_Enabled)
81 return;
82
62 base.AddRegion(scene); 83 base.AddRegion(scene);
63 84
64 scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed); 85 scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
86 }
87
88 public override void RegionLoaded(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 base.RegionLoaded(scene);
94 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
95
96 if (featuresModule != null)
97 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
98
99 m_UserManagement = m_scene.RequestModuleInterface<IUserManagement>();
100
101 }
102
103 public override void RemoveRegion(Scene scene)
104 {
105 if (!m_Enabled)
106 return;
107
108 scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
65 } 109 }
66 110
67 public override string Name 111 public override string Name
@@ -85,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
85 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's 129 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
86 } 130 }
87 131
88 m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); 132 m_log.DebugFormat("[HG MAP]: Resetting {0} blocks", mapBlocks.Count);
89 sp.ControllingClient.SendMapBlock(mapBlocks, 0); 133 sp.ControllingClient.SendMapBlock(mapBlocks, 0);
90 m_SeenMapBlocks.Remove(clientID); 134 m_SeenMapBlocks.Remove(clientID);
91 } 135 }
@@ -115,6 +159,20 @@ namespace OpenSim.Region.CoreModules.Hypergrid
115 return mapBlocks; 159 return mapBlocks;
116 } 160 }
117 161
162 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
163 {
164 if (m_UserManagement != null && !string.IsNullOrEmpty(m_MapImageServerURL) && !m_UserManagement.IsLocalGridUser(agentID))
165 {
166 OSD extras = new OSDMap();
167 if (features.ContainsKey("OpenSimExtras"))
168 extras = features["OpenSimExtras"];
169 else
170 features["OpenSimExtras"] = extras;
171
172 ((OSDMap)extras)["map-server-url"] = m_MapImageServerURL;
173
174 }
175 }
118 } 176 }
119 177
120 class MapArea 178 class MapArea
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index bfe0383..9809c86 100644
--- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
35 35
36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")] 36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 2b13a8b..5541063 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -412,7 +412,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
412 //public bool HttpVerboseThrottle = true; // not implemented 412 //public bool HttpVerboseThrottle = true; // not implemented
413 public List<string> HttpCustomHeaders = null; 413 public List<string> HttpCustomHeaders = null;
414 public bool HttpPragmaNoCache = true; 414 public bool HttpPragmaNoCache = true;
415 private Thread httpThread;
416 415
417 // Request info 416 // Request info
418 private UUID _itemID; 417 private UUID _itemID;
@@ -501,9 +500,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
501 Request.Headers.Add(HttpCustomHeaders[i], 500 Request.Headers.Add(HttpCustomHeaders[i],
502 HttpCustomHeaders[i+1]); 501 HttpCustomHeaders[i+1]);
503 } 502 }
504 if (proxyurl != null && proxyurl.Length > 0) 503 if (!string.IsNullOrEmpty(proxyurl))
505 { 504 {
506 if (proxyexcepts != null && proxyexcepts.Length > 0) 505 if (!string.IsNullOrEmpty(proxyexcepts))
507 { 506 {
508 string[] elist = proxyexcepts.Split(';'); 507 string[] elist = proxyexcepts.Split(';');
509 Request.Proxy = new WebProxy(proxyurl, true, elist); 508 Request.Proxy = new WebProxy(proxyurl, true, elist);
@@ -521,7 +520,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
521 Request.Headers[entry.Key] = entry.Value; 520 Request.Headers[entry.Key] = entry.Value;
522 521
523 // Encode outbound data 522 // Encode outbound data
524 if (OutboundBody.Length > 0) 523 if (!string.IsNullOrEmpty(OutboundBody))
525 { 524 {
526 byte[] data = Util.UTF8.GetBytes(OutboundBody); 525 byte[] data = Util.UTF8.GetBytes(OutboundBody);
527 526
@@ -622,7 +621,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
622 { 621 {
623 if (!WorkItem.Cancel()) 622 if (!WorkItem.Cancel())
624 { 623 {
625 WorkItem.Abort(); 624 WorkItem.Cancel(true);
626 } 625 }
627 } 626 }
628 catch (Exception) 627 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
new file mode 100644
index 0000000..e812d81
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
@@ -0,0 +1,198 @@
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.Net;
32using System.Reflection;
33using System.Runtime.Serialization;
34using System.Text;
35using System.Threading;
36using log4net.Config;
37using NUnit.Framework;
38using OpenMetaverse;
39using OpenMetaverse.Assets;
40using OpenSim.Framework;
41using OpenSim.Region.CoreModules.Scripting.HttpRequest;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Mock;
45
46namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
47{
48 class TestWebRequestCreate : IWebRequestCreate
49 {
50 public TestWebRequest NextRequest { get; set; }
51
52 public WebRequest Create(Uri uri)
53 {
54// NextRequest.RequestUri = uri;
55
56 return NextRequest;
57
58// return new TestWebRequest(new SerializationInfo(typeof(TestWebRequest), new FormatterConverter()), new StreamingContext());
59 }
60 }
61
62 class TestWebRequest : WebRequest
63 {
64 public override string ContentType { get; set; }
65 public override string Method { get; set; }
66
67 public Func<IAsyncResult, WebResponse> OnEndGetResponse { get; set; }
68
69 public TestWebRequest() : base()
70 {
71// Console.WriteLine("created");
72 }
73
74// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext)
75// : base(serializationInfo, streamingContext)
76// {
77// Console.WriteLine("created");
78// }
79
80 public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
81 {
82// Console.WriteLine("bish");
83 TestAsyncResult tasr = new TestAsyncResult();
84 callback(tasr);
85
86 return tasr;
87 }
88
89 public override WebResponse EndGetResponse(IAsyncResult asyncResult)
90 {
91// Console.WriteLine("bosh");
92 return OnEndGetResponse(asyncResult);
93 }
94 }
95
96 class TestHttpWebResponse : HttpWebResponse
97 {
98 public string Response { get; set; }
99
100 public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext)
101 : base(serializationInfo, streamingContext) {}
102
103 public override Stream GetResponseStream()
104 {
105 return new MemoryStream(Encoding.UTF8.GetBytes(Response));
106 }
107 }
108
109 class TestAsyncResult : IAsyncResult
110 {
111 WaitHandle m_wh = new ManualResetEvent(true);
112
113 object IAsyncResult.AsyncState
114 {
115 get {
116 throw new System.NotImplementedException ();
117 }
118 }
119
120 WaitHandle IAsyncResult.AsyncWaitHandle
121 {
122 get { return m_wh; }
123 }
124
125 bool IAsyncResult.CompletedSynchronously
126 {
127 get { return false; }
128 }
129
130 bool IAsyncResult.IsCompleted
131 {
132 get { return true; }
133 }
134 }
135
136 /// <summary>
137 /// Test script http request code.
138 /// </summary>
139 /// <remarks>
140 /// This class uses some very hacky workarounds in order to mock HttpWebResponse which are Mono dependent (though
141 /// alternative code can be written to make this work for Windows). However, the value of being able to
142 /// regression test this kind of code is very high.
143 /// </remarks>
144 [TestFixture]
145 public class ScriptsHttpRequestsTests : OpenSimTestCase
146 {
147 /// <summary>
148 /// Test what happens when we get a 404 response from a call.
149 /// </summary>
150 [Test]
151 public void Test404Response()
152 {
153 TestHelpers.InMethod();
154// TestHelpers.EnableLogging();
155
156 if (!Util.IsPlatformMono)
157 Assert.Ignore("Ignoring test since can only currently run on Mono");
158
159 string rawResponse = "boom";
160
161 TestWebRequestCreate twrc = new TestWebRequestCreate();
162
163 TestWebRequest twr = new TestWebRequest();
164 //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext());
165 twr.OnEndGetResponse += ar =>
166 {
167 SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter());
168 StreamingContext sc = new StreamingContext();
169// WebHeaderCollection headers = new WebHeaderCollection();
170// si.AddValue("m_HttpResponseHeaders", headers);
171 si.AddValue("uri", new Uri("test://arrg"));
172// si.AddValue("m_Certificate", null);
173 si.AddValue("version", HttpVersion.Version11);
174 si.AddValue("statusCode", HttpStatusCode.NotFound);
175 si.AddValue("contentLength", 0);
176 si.AddValue("method", "GET");
177 si.AddValue("statusDescription", "Not Found");
178 si.AddValue("contentType", null);
179 si.AddValue("cookieCollection", new CookieCollection());
180
181 TestHttpWebResponse thwr = new TestHttpWebResponse(si, sc);
182 thwr.Response = rawResponse;
183
184 throw new WebException("no message", null, WebExceptionStatus.ProtocolError, thwr);
185 };
186
187 twrc.NextRequest = twr;
188
189 WebRequest.RegisterPrefix("test", twrc);
190 HttpRequestClass hr = new HttpRequestClass();
191 hr.Url = "test://something";
192 hr.SendRequest();
193
194 Assert.That(hr.Status, Is.EqualTo((int)HttpStatusCode.NotFound));
195 Assert.That(hr.ResponseBody, Is.EqualTo(rawResponse));
196 }
197 }
198} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 2a4d440..1983fed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -219,7 +219,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
219 219
220 string uri = "/lslhttp/" + urlcode.ToString(); 220 string uri = "/lslhttp/" + urlcode.ToString();
221 221
222 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 222 PollServiceEventArgs args
223 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
223 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
224 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
225 226
@@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
266 267
267 string uri = "/lslhttps/" + urlcode.ToString(); 268 string uri = "/lslhttps/" + urlcode.ToString();
268 269
269 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 270 PollServiceEventArgs args
271 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
270 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
271 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
272 274
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 65737fa..baf9f2f 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -161,9 +161,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
161 { 161 {
162 WebRequest request = HttpWebRequest.Create(url); 162 WebRequest request = HttpWebRequest.Create(url);
163 163
164 if (m_proxyurl != null && m_proxyurl.Length > 0) 164 if (!string.IsNullOrEmpty(m_proxyurl))
165 { 165 {
166 if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) 166 if (!string.IsNullOrEmpty(m_proxyexcepts))
167 { 167 {
168 string[] elist = m_proxyexcepts.Split(';'); 168 string[] elist = m_proxyexcepts.Split(';');
169 request.Proxy = new WebProxy(m_proxyurl, true, elist); 169 request.Proxy = new WebProxy(m_proxyurl, true, elist);
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index fccf053..ad33f23 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -45,6 +45,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static string LogHeader = "[MODULE COMMS]";
48 49
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>(); 50 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50 51
@@ -148,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); 149 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
149 if (mi == null) 150 if (mi == null)
150 { 151 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); 152 m_log.WarnFormat("{0} Failed to register method {1}", LogHeader, meth);
152 return; 153 return;
153 } 154 }
154 155
@@ -163,9 +164,9 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
163 164
164 public void RegisterScriptInvocation(object target, MethodInfo mi) 165 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 { 166 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); 167// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
167 168
168 Type delegateType; 169 Type delegateType = typeof(void);
169 List<Type> typeArgs = mi.GetParameters() 170 List<Type> typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType) 171 .Select(p => p.ParameterType)
171 .ToList(); 172 .ToList();
@@ -176,8 +177,16 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
176 } 177 }
177 else 178 else
178 { 179 {
179 typeArgs.Add(mi.ReturnType); 180 try
180 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 181 {
182 typeArgs.Add(mi.ReturnType);
183 delegateType = Expression.GetFuncType(typeArgs.ToArray());
184 }
185 catch (Exception e)
186 {
187 m_log.ErrorFormat("{0} Failed to create function signature. Most likely more than 5 parameters. Method={1}. Error={2}",
188 LogHeader, mi.Name, e);
189 }
181 } 190 }
182 191
183 Delegate fcall; 192 Delegate fcall;
@@ -325,7 +334,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
325 /// </summary> 334 /// </summary>
326 public void RegisterConstant(string cname, object value) 335 public void RegisterConstant(string cname, object value)
327 { 336 {
328 m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); 337// m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
329 lock (m_constants) 338 lock (m_constants)
330 { 339 {
331 m_constants.Add(cname,value); 340 m_constants.Add(cname,value);
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 41baccc..7119137 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
152 TestHelpers.InMethod(); 152 TestHelpers.InMethod();
153 153
154 string dtText 154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; 155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png";
156 156
157 SetupScene(false); 157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
@@ -307,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
307 TestHelpers.InMethod(); 307 TestHelpers.InMethod();
308 308
309 string dtText 309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; 310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png";
311 311
312 SetupScene(true); 312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index cbffca7..c6e05b1 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -677,7 +677,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
677 // if not, use as method name 677 // if not, use as method name
678 UUID parseUID; 678 UUID parseUID;
679 string mName = "llRemoteData"; 679 string mName = "llRemoteData";
680 if ((Channel != null) && (Channel != "")) 680 if (!string.IsNullOrEmpty(Channel))
681 if (!UUID.TryParse(Channel, out parseUID)) 681 if (!UUID.TryParse(Channel, out parseUID))
682 mName = Channel; 682 mName = Channel;
683 else 683 else
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
new file mode 100644
index 0000000..323535a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
@@ -0,0 +1,226 @@
1
2/*
3 * Copyright (c) Contributors, http://opensimulator.org/
4 * See CONTRIBUTORS.TXT for a full list of copyright holders.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the OpenSimulator Project nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29using log4net;
30using Mono.Addins;
31using Nini.Config;
32using System;
33using System.Collections.Generic;
34using System.Reflection;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37using OpenSim.Server.Base;
38using OpenSim.Server.Handlers;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Framework.Servers;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenMetaverse;
46
47namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalUserProfilesServicesConnector")]
50 public class LocalUserProfilesServicesConnector : ISharedRegionModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Dictionary<UUID, Scene> regions = new Dictionary<UUID, Scene>();
57
58 public IUserProfilesService ServiceModule
59 {
60 get; private set;
61 }
62
63 public bool Enabled
64 {
65 get; private set;
66 }
67
68 public string Name
69 {
70 get
71 {
72 return "LocalUserProfilesServicesConnector";
73 }
74 }
75
76 public string ConfigName
77 {
78 get; private set;
79 }
80
81 public Type ReplaceableInterface
82 {
83 get { return null; }
84 }
85
86 public LocalUserProfilesServicesConnector()
87 {
88 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params");
89 }
90
91 public LocalUserProfilesServicesConnector(IConfigSource source)
92 {
93 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly.");
94 InitialiseService(source);
95 }
96
97 public void InitialiseService(IConfigSource source)
98 {
99 ConfigName = "UserProfilesService";
100
101 // Instantiate the request handler
102 IHttpServer Server = MainServer.Instance;
103
104 IConfig config = source.Configs[ConfigName];
105 if (config == null)
106 {
107 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini");
108 return;
109 }
110
111 if(!config.GetBoolean("Enabled",false))
112 {
113 Enabled = false;
114 return;
115 }
116
117 Enabled = true;
118
119 string serviceDll = config.GetString("LocalServiceModule",
120 String.Empty);
121
122 if (serviceDll == String.Empty)
123 {
124 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: No LocalServiceModule named in section UserProfilesService");
125 return;
126 }
127
128 Object[] args = new Object[] { source, ConfigName };
129 ServiceModule =
130 ServerUtils.LoadPlugin<IUserProfilesService>(serviceDll,
131 args);
132
133 if (ServiceModule == null)
134 {
135 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: Can't load user profiles service");
136 return;
137 }
138
139 Enabled = true;
140
141 JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
142
143 Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest);
144 Server.AddJsonRPCHandler("classified_update", handler.ClassifiedUpdate);
145 Server.AddJsonRPCHandler("classifieds_info_query", handler.ClassifiedInfoRequest);
146 Server.AddJsonRPCHandler("classified_delete", handler.ClassifiedDelete);
147 Server.AddJsonRPCHandler("avatarpicksrequest", handler.AvatarPicksRequest);
148 Server.AddJsonRPCHandler("pickinforequest", handler.PickInfoRequest);
149 Server.AddJsonRPCHandler("picks_update", handler.PicksUpdate);
150 Server.AddJsonRPCHandler("picks_delete", handler.PicksDelete);
151 Server.AddJsonRPCHandler("avatarnotesrequest", handler.AvatarNotesRequest);
152 Server.AddJsonRPCHandler("avatar_notes_update", handler.NotesUpdate);
153 Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest);
154 Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate);
155 Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate);
156 Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest);
157 Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData);
158 Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData);
159
160 }
161
162 #region ISharedRegionModule implementation
163
164 void ISharedRegionModule.PostInitialise()
165 {
166 if(!Enabled)
167 return;
168 }
169
170 #endregion
171
172 #region IRegionModuleBase implementation
173
174 void IRegionModuleBase.Initialise(IConfigSource source)
175 {
176 IConfig moduleConfig = source.Configs["Modules"];
177 if (moduleConfig != null)
178 {
179 string name = moduleConfig.GetString("UserProfilesServices", "");
180 if (name == Name)
181 {
182 InitialiseService(source);
183 m_log.Info("[LOCAL USERPROFILES SERVICE CONNECTOR]: Local user profiles connector enabled");
184 }
185 }
186 }
187
188 void IRegionModuleBase.Close()
189 {
190 return;
191 }
192
193 void IRegionModuleBase.AddRegion(Scene scene)
194 {
195 if (!Enabled)
196 return;
197
198 lock (regions)
199 {
200 if (regions.ContainsKey(scene.RegionInfo.RegionID))
201 m_log.ErrorFormat("[LOCAL USERPROFILES SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
202 else
203 regions.Add(scene.RegionInfo.RegionID, scene);
204 }
205 }
206
207 void IRegionModuleBase.RemoveRegion(Scene scene)
208 {
209 if (!Enabled)
210 return;
211
212 lock (regions)
213 {
214 if (regions.ContainsKey(scene.RegionInfo.RegionID))
215 regions.Remove(scene.RegionInfo.RegionID);
216 }
217 }
218
219 void IRegionModuleBase.RegionLoaded(Scene scene)
220 {
221 if (!Enabled)
222 return;
223 }
224 #endregion
225 }
226} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index d221d68..9f58175 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -322,7 +322,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
322 // a copy of the local asset. 322 // a copy of the local asset.
323 m_Cache.Cache(asset); 323 m_Cache.Cache(asset);
324 324
325 if (asset.Temporary || asset.Local) 325 if (asset.Local)
326 { 326 {
327 if (m_Cache != null) 327 if (m_Cache != null)
328 m_Cache.Cache(asset); 328 m_Cache.Cache(asset);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 480cd69..52b1039 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -258,7 +258,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
258 if (m_Cache != null) 258 if (m_Cache != null)
259 m_Cache.Cache(asset); 259 m_Cache.Cache(asset);
260 260
261 if (asset.Temporary || asset.Local) 261 if (asset.Local)
262 { 262 {
263// m_log.DebugFormat( 263// m_log.DebugFormat(
264// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}", 264// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}",
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
index 1982473..4f75191 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common;
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class AssetConnectorsTests : OpenSimTestCase 45 public class AssetConnectorTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestAddAsset() 48 public void TestAddAsset()
@@ -77,7 +77,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
77 // TODO: Add cache and check that this does receive a copy of the asset 77 // TODO: Add cache and check that this does receive a copy of the asset
78 } 78 }
79 79
80 [Test]
81 public void TestAddTemporaryAsset() 80 public void TestAddTemporaryAsset()
82 { 81 {
83 TestHelpers.InMethod(); 82 TestHelpers.InMethod();
@@ -93,8 +92,45 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
93 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); 92 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
94 lasc.Initialise(config); 93 lasc.Initialise(config);
95 94
95 // If it is remote, it should be stored
96 AssetBase a2 = AssetHelpers.CreateNotecardAsset();
97 a2.Local = false;
98 a2.Temporary = true;
99
100 lasc.Store(a2);
101
102 AssetBase retreivedA2 = lasc.Get(a2.ID);
103 Assert.That(retreivedA2.ID, Is.EqualTo(a2.ID));
104 Assert.That(retreivedA2.Metadata.ID, Is.EqualTo(a2.Metadata.ID));
105 Assert.That(retreivedA2.Data.Length, Is.EqualTo(a2.Data.Length));
106
107 AssetMetadata retrievedA2Metadata = lasc.GetMetadata(a2.ID);
108 Assert.That(retrievedA2Metadata.ID, Is.EqualTo(a2.ID));
109
110 byte[] retrievedA2Data = lasc.GetData(a2.ID);
111 Assert.That(retrievedA2Data.Length, Is.EqualTo(a2.Data.Length));
112
113 // TODO: Add cache and check that this does receive a copy of the asset
114 }
115
116 [Test]
117 public void TestAddLocalAsset()
118 {
119 TestHelpers.InMethod();
120// TestHelpers.EnableLogging();
121
122 IConfigSource config = new IniConfigSource();
123 config.AddConfig("Modules");
124 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
125 config.AddConfig("AssetService");
126 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
127 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
128
129 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
130 lasc.Initialise(config);
131
96 AssetBase a1 = AssetHelpers.CreateNotecardAsset(); 132 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
97 a1.Temporary = true; 133 a1.Local = true;
98 134
99 lasc.Store(a1); 135 lasc.Store(a1);
100 136
@@ -106,7 +142,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
106 } 142 }
107 143
108 [Test] 144 [Test]
109 public void TestAddLocalAsset() 145 public void TestAddTemporaryLocalAsset()
110 { 146 {
111 TestHelpers.InMethod(); 147 TestHelpers.InMethod();
112// TestHelpers.EnableLogging(); 148// TestHelpers.EnableLogging();
@@ -121,8 +157,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
121 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); 157 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
122 lasc.Initialise(config); 158 lasc.Initialise(config);
123 159
160 // If it is local, it should not be stored
124 AssetBase a1 = AssetHelpers.CreateNotecardAsset(); 161 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
125 a1.Local = true; 162 a1.Local = true;
163 a1.Temporary = true;
126 164
127 lasc.Store(a1); 165 lasc.Store(a1);
128 166
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index c0c2ca7..31ef79b 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
56 56
57 public LocalGridServicesConnector() 57 public LocalGridServicesConnector()
58 { 58 {
59 m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector no parms.");
59 } 60 }
60 61
61 public LocalGridServicesConnector(IConfigSource source) 62 public LocalGridServicesConnector(IConfigSource source)
@@ -142,10 +143,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
142 143
143 scene.RegisterModuleInterface<IGridService>(this); 144 scene.RegisterModuleInterface<IGridService>(this);
144 145
145 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) 146 lock (m_LocalCache)
146 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); 147 {
147 else 148 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
148 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene)); 149 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
150 else
151 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
152 }
149 } 153 }
150 154
151 public void RemoveRegion(Scene scene) 155 public void RemoveRegion(Scene scene)
@@ -153,8 +157,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
153 if (!m_Enabled) 157 if (!m_Enabled)
154 return; 158 return;
155 159
156 m_LocalCache[scene.RegionInfo.RegionID].Clear(); 160 lock (m_LocalCache)
157 m_LocalCache.Remove(scene.RegionInfo.RegionID); 161 {
162 m_LocalCache[scene.RegionInfo.RegionID].Clear();
163 m_LocalCache.Remove(scene.RegionInfo.RegionID);
164 }
158 } 165 }
159 166
160 public void RegionLoaded(Scene scene) 167 public void RegionLoaded(Scene scene)
@@ -191,12 +198,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
191 198
192 // First see if it's a neighbour, even if it isn't on this sim. 199 // First see if it's a neighbour, even if it isn't on this sim.
193 // Neighbour data is cached in memory, so this is fast 200 // Neighbour data is cached in memory, so this is fast
194 foreach (RegionCache rcache in m_LocalCache.Values) 201
202 lock (m_LocalCache)
195 { 203 {
196 region = rcache.GetRegionByPosition(x, y); 204 foreach (RegionCache rcache in m_LocalCache.Values)
197 if (region != null)
198 { 205 {
199 return region; 206 region = rcache.GetRegionByPosition(x, y);
207 if (region != null)
208 {
209 return region;
210 }
200 } 211 }
201 } 212 }
202 213
@@ -224,6 +235,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
224 return m_GridService.GetDefaultRegions(scopeID); 235 return m_GridService.GetDefaultRegions(scopeID);
225 } 236 }
226 237
238 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
239 {
240 return m_GridService.GetDefaultHypergridRegions(scopeID);
241 }
242
227 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 243 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
228 { 244 {
229 return m_GridService.GetFallbackRegions(scopeID, x, y); 245 return m_GridService.GetFallbackRegions(scopeID, x, y);
@@ -245,12 +261,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
245 { 261 {
246 System.Text.StringBuilder caps = new System.Text.StringBuilder(); 262 System.Text.StringBuilder caps = new System.Text.StringBuilder();
247 263
248 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache) 264 lock (m_LocalCache)
249 { 265 {
250 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key); 266 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
251 List<GridRegion> regions = kvp.Value.GetNeighbours(); 267 {
252 foreach (GridRegion r in regions) 268 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
253 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize); 269 List<GridRegion> regions = kvp.Value.GetNeighbours();
270 foreach (GridRegion r in regions)
271 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
272 }
254 } 273 }
255 274
256 MainConsole.Instance.Output(caps.ToString()); 275 MainConsole.Instance.Output(caps.ToString());
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index b2646ba..6a57d1f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -277,6 +277,26 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
277 return rinfo; 277 return rinfo;
278 } 278 }
279 279
280 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
281 {
282 List<GridRegion> rinfo = m_LocalGridService.GetDefaultHypergridRegions(scopeID);
283 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetDefaultHypergridRegions {0} found {1} regions", name, rinfo.Count);
284 List<GridRegion> grinfo = m_RemoteGridService.GetDefaultHypergridRegions(scopeID);
285
286 if (grinfo != null)
287 {
288 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultHypergridRegions {0} found {1} regions", name, grinfo.Count);
289 foreach (GridRegion r in grinfo)
290 {
291 m_RegionInfoCache.Cache(r);
292 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
293 rinfo.Add(r);
294 }
295 }
296
297 return rinfo;
298 }
299
280 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 300 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
281 { 301 {
282 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y); 302 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 221f815..e05d186 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -81,6 +81,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
81 81
82 public void OnConnectionClose(IClientAPI client) 82 public void OnConnectionClose(IClientAPI client)
83 { 83 {
84 if (client == null)
85 return;
86 if (client.SceneAgent == null)
87 return;
88
84 if (client.SceneAgent.IsChildAgent) 89 if (client.SceneAgent.IsChildAgent)
85 return; 90 return;
86 91
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index e474ef6..77a3c82 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -233,6 +233,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
233 if (sp != null) 233 if (sp != null)
234 { 234 {
235 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 235 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
236 if (aCircuit == null)
237 return;
238 if (aCircuit.ServiceURLs == null)
239 return;
240
236 if (aCircuit.ServiceURLs.ContainsKey("InventoryServerURI")) 241 if (aCircuit.ServiceURLs.ContainsKey("InventoryServerURI"))
237 { 242 {
238 inventoryURL = aCircuit.ServiceURLs["InventoryServerURI"].ToString(); 243 inventoryURL = aCircuit.ServiceURLs["InventoryServerURI"].ToString();
@@ -254,7 +259,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
254 if (sp == null) 259 if (sp == null)
255 { 260 {
256 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); 261 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
257 if (inventoryURL != null && inventoryURL != string.Empty) 262 if (!string.IsNullOrEmpty(inventoryURL))
258 { 263 {
259 inventoryURL = inventoryURL.Trim(new char[] { '/' }); 264 inventoryURL = inventoryURL.Trim(new char[] { '/' });
260 m_InventoryURLs.Add(userID, inventoryURL); 265 m_InventoryURLs.Add(userID, inventoryURL);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
index 1e434b9..2fc8ee3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
@@ -1,11 +1,41 @@
1using System; 1/*
2using System.Collections.Generic; 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 */
3 27
28using System;
29using System.Collections.Generic;
30using System.Threading;
4using OpenSim.Framework; 31using OpenSim.Framework;
5using OpenMetaverse; 32using OpenMetaverse;
6 33
7namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory 34namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
8{ 35{
36 /// <summary>
37 /// Cache root and system inventory folders to reduce number of potentially remote inventory calls and associated holdups.
38 /// </summary>
9 public class InventoryCache 39 public class InventoryCache
10 { 40 {
11 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour 41 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour
@@ -16,8 +46,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
16 46
17 public void Cache(UUID userID, InventoryFolderBase root) 47 public void Cache(UUID userID, InventoryFolderBase root)
18 { 48 {
19 lock (m_RootFolders) 49 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
20 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
21 } 50 }
22 51
23 public InventoryFolderBase GetRootFolder(UUID userID) 52 public InventoryFolderBase GetRootFolder(UUID userID)
@@ -31,14 +60,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
31 60
32 public void Cache(UUID userID, AssetType type, InventoryFolderBase folder) 61 public void Cache(UUID userID, AssetType type, InventoryFolderBase folder)
33 { 62 {
34 lock (m_FolderTypes) 63 Dictionary<AssetType, InventoryFolderBase> ff = null;
64 if (!m_FolderTypes.TryGetValue(userID, out ff))
65 {
66 ff = new Dictionary<AssetType, InventoryFolderBase>();
67 m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS);
68 }
69
70 // We need to lock here since two threads could potentially retrieve the same dictionary
71 // and try to add a folder for that type simultaneously. Dictionary<>.Add() is not described as thread-safe in the SDK
72 // even if the folders are identical.
73 lock (ff)
35 { 74 {
36 Dictionary<AssetType, InventoryFolderBase> ff = null;
37 if (!m_FolderTypes.TryGetValue(userID, out ff))
38 {
39 ff = new Dictionary<AssetType, InventoryFolderBase>();
40 m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS);
41 }
42 if (!ff.ContainsKey(type)) 75 if (!ff.ContainsKey(type))
43 ff.Add(type, folder); 76 ff.Add(type, folder);
44 } 77 }
@@ -50,8 +83,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
50 if (m_FolderTypes.TryGetValue(userID, out ff)) 83 if (m_FolderTypes.TryGetValue(userID, out ff))
51 { 84 {
52 InventoryFolderBase f = null; 85 InventoryFolderBase f = null;
53 if (ff.TryGetValue(type, out f)) 86
54 return f; 87 lock (ff)
88 {
89 if (ff.TryGetValue(type, out f))
90 return f;
91 }
55 } 92 }
56 93
57 return null; 94 return null;
@@ -59,8 +96,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
59 96
60 public void Cache(UUID userID, InventoryCollection inv) 97 public void Cache(UUID userID, InventoryCollection inv)
61 { 98 {
62 lock (m_Inventories) 99 m_Inventories.AddOrUpdate(userID, inv, 120);
63 m_Inventories.AddOrUpdate(userID, inv, 120);
64 } 100 }
65 101
66 public InventoryCollection GetUserInventory(UUID userID) 102 public InventoryCollection GetUserInventory(UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index ec5751d..99913a9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -196,7 +196,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
196 Util.FireAndForget(delegate 196 Util.FireAndForget(delegate
197 { 197 {
198 foreach (InventoryItemBase item in items) 198 foreach (InventoryItemBase item in items)
199 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 199 if (!string.IsNullOrEmpty(item.CreatorData))
200 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
200 }); 201 });
201 } 202 }
202 203
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 2d3ba82..7f78076 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -195,18 +195,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
195 { 195 {
196 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); 196 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
197 197
198 if (invCol != null && UserManager != null) 198 // Commenting this for now, because it's causing more grief than good
199 { 199 //if (invCol != null && UserManager != null)
200 // Protect ourselves against the caller subsequently modifying the items list 200 //{
201 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); 201 // // Protect ourselves against the caller subsequently modifying the items list
202 202 // List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
203 if (items != null && items.Count > 0) 203
204 Util.FireAndForget(delegate 204 // if (items != null && items.Count > 0)
205 { 205 // //Util.FireAndForget(delegate
206 foreach (InventoryItemBase item in items) 206 // //{
207 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 207 // foreach (InventoryItemBase item in items)
208 }); 208 // if (!string.IsNullOrEmpty(item.CreatorData))
209 } 209 // UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
210 // //});
211 //}
210 212
211 return invCol; 213 return invCol;
212 } 214 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
index 172bea1..516ad40 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
79 79
80 public void OnConnectionClose(IClientAPI client) 80 public void OnConnectionClose(IClientAPI client)
81 { 81 {
82 if (!client.SceneAgent.IsChildAgent) 82 if (client != null && client.SceneAgent != null && !client.SceneAgent.IsChildAgent)
83 { 83 {
84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); 84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
85 m_PresenceService.LogoutAgent(client.SessionId); 85 m_PresenceService.LogoutAgent(client.SessionId);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 8b8bb37..7a6a174 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -46,9 +46,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 /// <summary> 48 /// <summary>
49 /// Version of this service 49 /// Version of this service.
50 /// </summary> 50 /// </summary>
51 private const string m_Version = "SIMULATION/0.1"; 51 /// <remarks>
52 /// Currently valid versions are "SIMULATION/0.1" and "SIMULATION/0.2"
53 /// </remarks>
54 public string ServiceVersion { get; set; }
52 55
53 /// <summary> 56 /// <summary>
54 /// Map region ID to scene. 57 /// Map region ID to scene.
@@ -62,28 +65,39 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
62 65
63 #region Region Module interface 66 #region Region Module interface
64 67
65 public void Initialise(IConfigSource config) 68 public void Initialise(IConfigSource configSource)
66 { 69 {
67 IConfig moduleConfig = config.Configs["Modules"]; 70 IConfig moduleConfig = configSource.Configs["Modules"];
68 if (moduleConfig != null) 71 if (moduleConfig != null)
69 { 72 {
70 string name = moduleConfig.GetString("SimulationServices", ""); 73 string name = moduleConfig.GetString("SimulationServices", "");
71 if (name == Name) 74 if (name == Name)
72 { 75 {
73 //IConfig userConfig = config.Configs["SimulationService"]; 76 InitialiseService(configSource);
74 //if (userConfig == null)
75 //{
76 // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
77 // return;
78 //}
79 77
80 m_ModuleEnabled = true; 78 m_ModuleEnabled = true;
81 79
82 m_log.Info("[SIMULATION CONNECTOR]: Local simulation enabled"); 80 m_log.Info("[LOCAL SIMULATION CONNECTOR]: Local simulation enabled.");
83 } 81 }
84 } 82 }
85 } 83 }
86 84
85 public void InitialiseService(IConfigSource configSource)
86 {
87 ServiceVersion = "SIMULATION/0.2";
88 IConfig config = configSource.Configs["SimulationService"];
89 if (config != null)
90 {
91 ServiceVersion = config.GetString("ConnectorProtocolVersion", ServiceVersion);
92
93 if (ServiceVersion != "SIMULATION/0.1" && ServiceVersion != "SIMULATION/0.2")
94 throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion));
95
96 m_log.InfoFormat(
97 "[LOCAL SIMULATION CONNECTOR]: Initialized with connector protocol version {0}", ServiceVersion);
98 }
99 }
100
87 public void PostInitialise() 101 public void PostInitialise()
88 { 102 {
89 } 103 }
@@ -160,7 +174,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
160 174
161 #endregion 175 #endregion
162 176
163 #region ISimulation 177 #region ISimulationService
164 178
165 public IScene GetScene(UUID regionId) 179 public IScene GetScene(UUID regionId)
166 { 180 {
@@ -221,7 +235,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
221// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 235// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
222// destination.RegionName, destination.RegionID); 236// destination.RegionName, destination.RegionID);
223 237
224 return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); 238 return m_scenes[destination.RegionID].IncomingUpdateChildAgent(cAgentData);
225 } 239 }
226 240
227// m_log.DebugFormat( 241// m_log.DebugFormat(
@@ -231,7 +245,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
231 return false; 245 return false;
232 } 246 }
233 247
234 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) 248 public bool UpdateAgent(GridRegion destination, AgentPosition agentPosition)
235 { 249 {
236 if (destination == null) 250 if (destination == null)
237 return false; 251 return false;
@@ -243,37 +257,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
243 foreach (Scene s in m_scenes.Values) 257 foreach (Scene s in m_scenes.Values)
244 { 258 {
245// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); 259// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
246 s.IncomingChildAgentDataUpdate(cAgentData); 260 s.IncomingUpdateChildAgent(agentPosition);
247 } 261 }
248 262
249 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); 263 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
250 return true; 264 return true;
251 } 265 }
252 266
253 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
254 {
255 agent = null;
256
257 if (destination == null)
258 return false;
259
260 if (m_scenes.ContainsKey(destination.RegionID))
261 {
262// m_log.DebugFormat(
263// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
264// s.RegionInfo.RegionName, destination.RegionHandle);
265
266 return m_scenes[destination.RegionID].IncomingRetrieveRootAgent(id, out agent);
267 }
268
269 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
270 return false;
271 }
272
273 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 267 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
274 { 268 {
275 reason = "Communications failure"; 269 reason = "Communications failure";
276 version = m_Version; 270 version = ServiceVersion;
277 if (destination == null) 271 if (destination == null)
278 return false; 272 return false;
279 273
@@ -306,12 +300,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
306 return false; 300 return false;
307 } 301 }
308 302
309 public bool CloseChildAgent(GridRegion destination, UUID id) 303 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
310 {
311 return CloseAgent(destination, id);
312 }
313
314 public bool CloseAgent(GridRegion destination, UUID id)
315 { 304 {
316 if (destination == null) 305 if (destination == null)
317 return false; 306 return false;
@@ -322,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
322// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 311// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
323// s.RegionInfo.RegionName, destination.RegionHandle); 312// s.RegionInfo.RegionName, destination.RegionHandle);
324 313
325 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); 314 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
326 return true; 315 return true;
327 } 316 }
328 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 317 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
@@ -363,7 +352,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
363 return false; 352 return false;
364 } 353 }
365 354
366 #endregion /* IInterregionComms */ 355 #endregion
367 356
368 #region Misc 357 #region Misc
369 358
@@ -383,4 +372,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
383 372
384 #endregion 373 #endregion
385 } 374 }
386} 375} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index c8698ca..ab912ed 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -50,9 +50,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService 51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
52 { 52 {
53 private bool initialized = false;
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 54
55 private bool initialized = false;
56 protected bool m_enabled = false; 56 protected bool m_enabled = false;
57 protected Scene m_aScene; 57 protected Scene m_aScene;
58 // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module 58 // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module
@@ -64,27 +64,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
64 64
65 #region Region Module interface 65 #region Region Module interface
66 66
67 public virtual void Initialise(IConfigSource config) 67 public virtual void Initialise(IConfigSource configSource)
68 { 68 {
69 69 IConfig moduleConfig = configSource.Configs["Modules"];
70 IConfig moduleConfig = config.Configs["Modules"];
71 if (moduleConfig != null) 70 if (moduleConfig != null)
72 { 71 {
73 string name = moduleConfig.GetString("SimulationServices", ""); 72 string name = moduleConfig.GetString("SimulationServices", "");
74 if (name == Name) 73 if (name == Name)
75 { 74 {
76 //IConfig userConfig = config.Configs["SimulationService"]; 75 m_localBackend = new LocalSimulationConnectorModule();
77 //if (userConfig == null) 76
78 //{ 77 m_localBackend.InitialiseService(configSource);
79 // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
80 // return;
81 //}
82 78
83 m_remoteConnector = new SimulationServiceConnector(); 79 m_remoteConnector = new SimulationServiceConnector();
84 80
85 m_enabled = true; 81 m_enabled = true;
86 82
87 m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled"); 83 m_log.Info("[REMOTE SIMULATION CONNECTOR]: Remote simulation enabled.");
88 } 84 }
89 } 85 }
90 } 86 }
@@ -142,8 +138,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
142 } 138 }
143 139
144 protected virtual void InitOnce(Scene scene) 140 protected virtual void InitOnce(Scene scene)
145 { 141 {
146 m_localBackend = new LocalSimulationConnectorModule();
147 m_aScene = scene; 142 m_aScene = scene;
148 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService); 143 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
149 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName); 144 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
@@ -151,7 +146,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
151 146
152 #endregion 147 #endregion
153 148
154 #region IInterregionComms 149 #region ISimulationService
155 150
156 public IScene GetScene(UUID regionId) 151 public IScene GetScene(UUID regionId)
157 { 152 {
@@ -194,7 +189,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
194 return false; 189 return false;
195 190
196 // Try local first 191 // Try local first
197 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 192 if (m_localBackend.IsLocalRegion(destination.RegionID))
198 return m_localBackend.UpdateAgent(destination, cAgentData); 193 return m_localBackend.UpdateAgent(destination, cAgentData);
199 194
200 return m_remoteConnector.UpdateAgent(destination, cAgentData); 195 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -206,30 +201,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
206 return false; 201 return false;
207 202
208 // Try local first 203 // Try local first
209 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 204 if (m_localBackend.IsLocalRegion(destination.RegionID))
210 return m_localBackend.UpdateAgent(destination, cAgentData); 205 return m_localBackend.UpdateAgent(destination, cAgentData);
211 206
212 return m_remoteConnector.UpdateAgent(destination, cAgentData); 207 return m_remoteConnector.UpdateAgent(destination, cAgentData);
213 } 208 }
214 209
215 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
216 {
217 agent = null;
218
219 if (destination == null)
220 return false;
221
222 // Try local first
223 if (m_localBackend.RetrieveAgent(destination, id, out agent))
224 return true;
225
226 // else do the remote thing
227 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
228 return m_remoteConnector.RetrieveAgent(destination, id, out agent);
229
230 return false;
231 }
232
233 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 210 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
234 { 211 {
235 reason = "Communications failure"; 212 reason = "Communications failure";
@@ -262,34 +239,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
262 return false; 239 return false;
263 } 240 }
264 241
265 public bool CloseChildAgent(GridRegion destination, UUID id) 242 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
266 {
267 if (destination == null)
268 return false;
269
270 // Try local first
271 if (m_localBackend.CloseChildAgent(destination, id))
272 return true;
273
274 // else do the remote thing
275 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
276 return m_remoteConnector.CloseChildAgent(destination, id);
277
278 return false;
279 }
280
281 public bool CloseAgent(GridRegion destination, UUID id)
282 { 243 {
283 if (destination == null) 244 if (destination == null)
284 return false; 245 return false;
285 246
286 // Try local first 247 // Try local first
287 if (m_localBackend.CloseAgent(destination, id)) 248 if (m_localBackend.CloseAgent(destination, id, auth_token))
288 return true; 249 return true;
289 250
290 // else do the remote thing 251 // else do the remote thing
291 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 252 if (!m_localBackend.IsLocalRegion(destination.RegionID))
292 return m_remoteConnector.CloseAgent(destination, id); 253 return m_remoteConnector.CloseAgent(destination, id, auth_token);
293 254
294 return false; 255 return false;
295 } 256 }
@@ -311,12 +272,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
311 } 272 }
312 273
313 // else do the remote thing 274 // else do the remote thing
314 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 275 if (!m_localBackend.IsLocalRegion(destination.RegionID))
315 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); 276 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
316 277
317 return false; 278 return false;
318 } 279 }
319 280
320 #endregion /* IInterregionComms */ 281 #endregion
321 } 282 }
322} 283}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index fcfdf7c..efc4998 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -464,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
464 // or creator data is present. Otherwise, use the estate owner instead. 464 // or creator data is present. Otherwise, use the estate owner instead.
465 foreach (SceneObjectPart part in sceneObject.Parts) 465 foreach (SceneObjectPart part in sceneObject.Parts)
466 { 466 {
467 if (part.CreatorData == null || part.CreatorData == string.Empty) 467 if (string.IsNullOrEmpty(part.CreatorData))
468 { 468 {
469 if (!ResolveUserUuid(scene, part.CreatorID)) 469 if (!ResolveUserUuid(scene, part.CreatorID))
470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
@@ -515,7 +515,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
516 } 516 }
517 517
518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 518 if (string.IsNullOrEmpty(kvp.Value.CreatorData))
519 { 519 {
520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) 520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index a990898..7a844f4 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 ada7ecc..6c2a631 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 4d49794..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>]",
@@ -76,6 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.", 76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
77 consoleSetTerrainHeights); 77 consoleSetTerrainHeights);
78 78
79 m_module.Scene.AddCommand("Regions", m_module, "set water height",
80 "set water height <height> [<x>] [<y>]",
81 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
82 "Specify -1 in <x> or <y> to wildcard that coordinate.",
83 consoleSetWaterHeight);
84
85
79 m_module.Scene.AddCommand( 86 m_module.Scene.AddCommand(
80 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand); 87 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
81 } 88 }
@@ -121,7 +128,29 @@ namespace OpenSim.Region.CoreModules.World.Estate
121 } 128 }
122 } 129 }
123 } 130 }
124 131 protected void consoleSetWaterHeight(string module, string[] args)
132 {
133 string heightstring = args[3];
134
135 int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
136 int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
137
138 if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
139 {
140 if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
141 {
142 double selectedheight = double.Parse(heightstring);
143
144 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
145 string.Format(" {0}", selectedheight));
146 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
147
148 m_module.Scene.RegionInfo.RegionSettings.Save();
149 m_module.TriggerRegionInfoChange();
150 m_module.sendRegionHandshakeToAll();
151 }
152 }
153 }
125 protected void consoleSetTerrainHeights(string module, string[] args) 154 protected void consoleSetTerrainHeights(string module, string[] args)
126 { 155 {
127 string num = args[3]; 156 string num = args[3];
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 834fd77..47390e7 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -576,7 +576,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
576 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 576 if (!Scene.TeleportClientHome(user, s.ControllingClient))
577 { 577 {
578 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 578 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
579 s.ControllingClient.Close(); 579 Scene.CloseAgent(s.UUID, false);
580 } 580 }
581 } 581 }
582 } 582 }
@@ -716,7 +716,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
716 } 716 }
717 } 717 }
718 718
719 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 719 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
720 { 720 {
721 SceneObjectPart part; 721 SceneObjectPart part;
722 722
@@ -756,7 +756,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
756 default: 756 default:
757 break; 757 break;
758 } 758 }
759 SendTelehubInfo(client); 759
760 if (client != null)
761 SendTelehubInfo(client);
760 } 762 }
761 763
762 private void SendSimulatorBlueBoxMessage( 764 private void SendSimulatorBlueBoxMessage(
@@ -811,7 +813,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
811 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 813 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
812 { 814 {
813 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 815 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
814 s.ControllingClient.Close(); 816 Scene.CloseAgent(s.UUID, false);
815 } 817 }
816 } 818 }
817 } 819 }
@@ -834,7 +836,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
834 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) 836 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
835 { 837 {
836 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 838 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
837 p.ControllingClient.Close(); 839 Scene.CloseAgent(p.UUID, false);
838 } 840 }
839 } 841 }
840 } 842 }
@@ -843,26 +845,23 @@ namespace OpenSim.Region.CoreModules.World.Estate
843 845
844 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 846 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
845 { 847 {
846 if (TerrainUploader != null) 848 lock (this)
847 { 849 {
848 lock (TerrainUploader) 850 if ((TerrainUploader != null) && (XferID == TerrainUploader.XferID))
849 { 851 {
850 if (XferID == TerrainUploader.XferID) 852 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
851 { 853 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
852 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 854 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
853 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
854 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
855 855
856 TerrainUploader = null; 856 TerrainUploader = null;
857 remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); 857 remoteClient.SendAlertMessage("Terrain Upload aborted by the client");
858 }
859 } 858 }
860 } 859 }
861
862 } 860 }
861
863 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) 862 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient)
864 { 863 {
865 lock (TerrainUploader) 864 lock (this)
866 { 865 {
867 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 866 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
868 remoteClient.OnAbortXfer -= AbortTerrainXferHandler; 867 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
@@ -921,22 +920,32 @@ namespace OpenSim.Region.CoreModules.World.Estate
921 920
922 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) 921 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName)
923 { 922 {
924 if (TerrainUploader == null) 923 lock (this)
925 { 924 {
926 925 if (TerrainUploader == null)
927 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
928 lock (TerrainUploader)
929 { 926 {
927 m_log.DebugFormat("Starting to receive uploaded terrain");
928 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
930 remote_client.OnXferReceive += TerrainUploader.XferReceive; 929 remote_client.OnXferReceive += TerrainUploader.XferReceive;
931 remote_client.OnAbortXfer += AbortTerrainXferHandler; 930 remote_client.OnAbortXfer += AbortTerrainXferHandler;
932 TerrainUploader.TerrainUploadDone += HandleTerrainApplication; 931 TerrainUploader.TerrainUploadDone += HandleTerrainApplication;
932 TerrainUploader.RequestStartXfer(remote_client);
933 }
934 else
935 {
936 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!");
933 } 937 }
934 TerrainUploader.RequestStartXfer(remote_client);
935
936 } 938 }
937 else 939 }
940
941 public bool IsTerrainXfer(ulong xferID)
942 {
943 lock (this)
938 { 944 {
939 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); 945 if (TerrainUploader == null)
946 return false;
947 else
948 return TerrainUploader.XferID == xferID;
940 } 949 }
941 } 950 }
942 951
@@ -1221,7 +1230,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1221 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; 1230 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest;
1222 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; 1231 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest;
1223 client.OnEstateChangeInfo += handleEstateChangeInfo; 1232 client.OnEstateChangeInfo += handleEstateChangeInfo;
1224 client.OnEstateManageTelehub += handleOnEstateManageTelehub; 1233 client.OnEstateManageTelehub += HandleOnEstateManageTelehub;
1225 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; 1234 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest;
1226 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; 1235 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
1227 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; 1236 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
index b8d8b10..2d74eaf 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
@@ -78,7 +78,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
78 /// <param name="data"></param> 78 /// <param name="data"></param>
79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) 79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
80 { 80 {
81 if (mXferID == xferID) 81 if (mXferID != xferID)
82 return;
83
84 lock (this)
82 { 85 {
83 if (m_asset.Data.Length > 1) 86 if (m_asset.Data.Length > 1)
84 { 87 {
@@ -99,7 +102,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 if ((packetID & 0x80000000) != 0) 102 if ((packetID & 0x80000000) != 0)
100 { 103 {
101 SendCompleteMessage(remoteClient); 104 SendCompleteMessage(remoteClient);
102
103 } 105 }
104 } 106 }
105 } 107 }
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
new file mode 100644
index 0000000..73e706c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
@@ -0,0 +1,218 @@
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.Reflection;
31
32using OpenSim.Services.Interfaces;
33using GridRegion = OpenSim.Services.Interfaces.GridRegion;
34using OpenSim.Server.Base;
35using OpenSim.Framework.Servers.HttpServer;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Scenes;
38
39using OpenMetaverse;
40using log4net;
41
42namespace OpenSim.Region.CoreModules.World.Estate
43{
44 public class EstateConnector
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected XEstateModule m_EstateModule;
49
50 public EstateConnector(XEstateModule module)
51 {
52 m_EstateModule = module;
53 }
54
55 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID)
56 {
57 Dictionary<string, object> sendData = new Dictionary<string, object>();
58 sendData["METHOD"] = "teleport_home_one_user";
59
60 sendData["EstateID"] = EstateID.ToString();
61 sendData["PreyID"] = PreyID.ToString();
62
63 SendToEstate(EstateID, sendData);
64 }
65
66 public void SendTeleportHomeAllUsers(uint EstateID)
67 {
68 Dictionary<string, object> sendData = new Dictionary<string, object>();
69 sendData["METHOD"] = "teleport_home_all_users";
70
71 sendData["EstateID"] = EstateID.ToString();
72
73 SendToEstate(EstateID, sendData);
74 }
75
76 public bool SendUpdateCovenant(uint EstateID, UUID CovenantID)
77 {
78 Dictionary<string, object> sendData = new Dictionary<string, object>();
79 sendData["METHOD"] = "update_covenant";
80
81 sendData["CovenantID"] = CovenantID.ToString();
82 sendData["EstateID"] = EstateID.ToString();
83
84 // Handle local regions locally
85 //
86 foreach (Scene s in m_EstateModule.Scenes)
87 {
88 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
89 s.RegionInfo.RegionSettings.Covenant = CovenantID;
90// s.ReloadEstateData();
91 }
92
93 SendToEstate(EstateID, sendData);
94
95 return true;
96 }
97
98 public bool SendUpdateEstate(uint EstateID)
99 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>();
101 sendData["METHOD"] = "update_estate";
102
103 sendData["EstateID"] = EstateID.ToString();
104
105 // Handle local regions locally
106 //
107 foreach (Scene s in m_EstateModule.Scenes)
108 {
109 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
110 s.ReloadEstateData();
111 }
112
113 SendToEstate(EstateID, sendData);
114
115 return true;
116 }
117
118 public void SendEstateMessage(uint EstateID, UUID FromID, string FromName, string Message)
119 {
120 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 sendData["METHOD"] = "estate_message";
122
123 sendData["EstateID"] = EstateID.ToString();
124 sendData["FromID"] = FromID.ToString();
125 sendData["FromName"] = FromName;
126 sendData["Message"] = Message;
127
128 SendToEstate(EstateID, sendData);
129 }
130
131 private void SendToEstate(uint EstateID, Dictionary<string, object> sendData)
132 {
133 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID);
134
135 UUID ScopeID = UUID.Zero;
136
137 // Handle local regions locally
138 //
139 lock (m_EstateModule.Scenes)
140 {
141 foreach (Scene s in m_EstateModule.Scenes)
142 {
143 if (regions.Contains(s.RegionInfo.RegionID))
144 {
145 // All regions in one estate are in the same scope.
146 // Use that scope.
147 //
148 ScopeID = s.RegionInfo.ScopeID;
149 regions.Remove(s.RegionInfo.RegionID);
150 }
151 }
152 }
153
154 // Our own region should always be in the above list.
155 // In a standalone this would not be true. But then,
156 // Scope ID is not relevat there. Use first scope.
157 //
158 if (ScopeID == UUID.Zero)
159 ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID;
160
161 // Don't send to the same instance twice
162 //
163 List<string> done = new List<string>();
164
165 // Send to remote regions
166 //
167 foreach (UUID regionID in regions)
168 {
169 GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID);
170 if (region != null)
171 {
172 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
173 if (done.Contains(url))
174 continue;
175
176 Call(region, sendData);
177 done.Add(url);
178 }
179 }
180 }
181
182 private bool Call(GridRegion region, Dictionary<string, object> sendData)
183 {
184 string reqString = ServerUtils.BuildQueryString(sendData);
185 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString);
186 try
187 {
188 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
189 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
190 url + "/estate",
191 reqString);
192 if (reply != string.Empty)
193 {
194 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
195
196 if (replyData.ContainsKey("RESULT"))
197 {
198 if (replyData["RESULT"].ToString().ToLower() == "true")
199 return true;
200 else
201 return false;
202 }
203 else
204 m_log.DebugFormat("[XESTATE CONNECTOR]: reply data does not contain result field");
205
206 }
207 else
208 m_log.DebugFormat("[XESTATE CONNECTOR]: received empty reply");
209 }
210 catch (Exception e)
211 {
212 m_log.DebugFormat("[XESTATE CONNECTOR]: Exception when contacting remote sim: {0}", e.Message);
213 }
214
215 return false;
216 }
217 }
218}
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
new file mode 100644
index 0000000..f54ab2c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
@@ -0,0 +1,256 @@
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;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Server.Base;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using Mono.Addins;
45
46namespace OpenSim.Region.CoreModules.World.Estate
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")]
49 public class XEstateModule : ISharedRegionModule
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 protected List<Scene> m_Scenes = new List<Scene>();
54 protected bool m_InInfoUpdate = false;
55
56 public bool InInfoUpdate
57 {
58 get { return m_InInfoUpdate; }
59 set { m_InInfoUpdate = value; }
60 }
61
62 public List<Scene> Scenes
63 {
64 get { return m_Scenes; }
65 }
66
67 protected EstateConnector m_EstateConnector;
68
69 public void Initialise(IConfigSource config)
70 {
71 int port = 0;
72
73 IConfig estateConfig = config.Configs["Estate"];
74 if (estateConfig != null)
75 {
76 port = estateConfig.GetInt("Port", 0);
77 }
78
79 m_EstateConnector = new EstateConnector(this);
80
81 // Instantiate the request handler
82 IHttpServer server = MainServer.GetHttpServer((uint)port);
83 server.AddStreamHandler(new EstateRequestHandler(this));
84 }
85
86 public void PostInitialise()
87 {
88 }
89
90 public void Close()
91 {
92 }
93
94 public void AddRegion(Scene scene)
95 {
96 lock (m_Scenes)
97 m_Scenes.Add(scene);
98
99 scene.EventManager.OnNewClient += OnNewClient;
100 }
101
102 public void RegionLoaded(Scene scene)
103 {
104 IEstateModule em = scene.RequestModuleInterface<IEstateModule>();
105
106 em.OnRegionInfoChange += OnRegionInfoChange;
107 em.OnEstateInfoChange += OnEstateInfoChange;
108 em.OnEstateMessage += OnEstateMessage;
109 }
110
111 public void RemoveRegion(Scene scene)
112 {
113 scene.EventManager.OnNewClient -= OnNewClient;
114
115 lock (m_Scenes)
116 m_Scenes.Remove(scene);
117 }
118
119 public string Name
120 {
121 get { return "EstateModule"; }
122 }
123
124 public Type ReplaceableInterface
125 {
126 get { return null; }
127 }
128
129 private Scene FindScene(UUID RegionID)
130 {
131 foreach (Scene s in Scenes)
132 {
133 if (s.RegionInfo.RegionID == RegionID)
134 return s;
135 }
136
137 return null;
138 }
139
140 private void OnRegionInfoChange(UUID RegionID)
141 {
142 Scene s = FindScene(RegionID);
143 if (s == null)
144 return;
145
146 if (!m_InInfoUpdate)
147 m_EstateConnector.SendUpdateCovenant(s.RegionInfo.EstateSettings.EstateID, s.RegionInfo.RegionSettings.Covenant);
148 }
149
150 private void OnEstateInfoChange(UUID RegionID)
151 {
152 Scene s = FindScene(RegionID);
153 if (s == null)
154 return;
155
156 if (!m_InInfoUpdate)
157 m_EstateConnector.SendUpdateEstate(s.RegionInfo.EstateSettings.EstateID);
158 }
159
160 private void OnEstateMessage(UUID RegionID, UUID FromID, string FromName, string Message)
161 {
162 Scene senderScenes = FindScene(RegionID);
163 if (senderScenes == null)
164 return;
165
166 uint estateID = senderScenes.RegionInfo.EstateSettings.EstateID;
167
168 foreach (Scene s in Scenes)
169 {
170 if (s.RegionInfo.EstateSettings.EstateID == estateID)
171 {
172 IDialogModule dm = s.RequestModuleInterface<IDialogModule>();
173
174 if (dm != null)
175 {
176 dm.SendNotificationToUsersInRegion(FromID, FromName,
177 Message);
178 }
179 }
180 }
181 if (!m_InInfoUpdate)
182 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
183 }
184
185 private void OnNewClient(IClientAPI client)
186 {
187 client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
188 client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
189
190 }
191
192 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey)
193 {
194 if (prey == UUID.Zero)
195 return;
196
197 if (!(client.Scene is Scene))
198 return;
199
200 Scene scene = (Scene)client.Scene;
201
202 uint estateID = scene.RegionInfo.EstateSettings.EstateID;
203
204 if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false))
205 return;
206
207 foreach (Scene s in Scenes)
208 {
209 if (s == scene)
210 continue; // Already handles by estate module
211 if (s.RegionInfo.EstateSettings.EstateID != estateID)
212 continue;
213
214 ScenePresence p = scene.GetScenePresence(prey);
215 if (p != null && !p.IsChildAgent)
216 {
217 p.ControllingClient.SendTeleportStart(16);
218 scene.TeleportClientHome(prey, p.ControllingClient);
219 }
220 }
221
222 m_EstateConnector.SendTeleportHomeOneUser(estateID, prey);
223 }
224
225 private void OnEstateTeleportAllUsersHomeRequest(IClientAPI client, UUID invoice, UUID senderID)
226 {
227 if (!(client.Scene is Scene))
228 return;
229
230 Scene scene = (Scene)client.Scene;
231
232 uint estateID = scene.RegionInfo.EstateSettings.EstateID;
233
234 if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false))
235 return;
236
237 foreach (Scene s in Scenes)
238 {
239 if (s == scene)
240 continue; // Already handles by estate module
241 if (s.RegionInfo.EstateSettings.EstateID != estateID)
242 continue;
243
244 scene.ForEachScenePresence(delegate(ScenePresence p) {
245 if (p != null && !p.IsChildAgent)
246 {
247 p.ControllingClient.SendTeleportStart(16);
248 scene.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient);
249 }
250 });
251 }
252
253 m_EstateConnector.SendTeleportHomeAllUsers(estateID);
254 }
255 }
256}
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
new file mode 100644
index 0000000..2366767
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
@@ -0,0 +1,298 @@
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.Xml;
33
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Framework.Interfaces;
39
40using OpenMetaverse;
41using log4net;
42
43namespace OpenSim.Region.CoreModules.World.Estate
44{
45 public class EstateRequestHandler : BaseStreamHandler
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 protected XEstateModule m_EstateModule;
50 protected Object m_RequestLock = new Object();
51
52 public EstateRequestHandler(XEstateModule fmodule)
53 : base("POST", "/estate")
54 {
55 m_EstateModule = fmodule;
56 }
57
58 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 {
61 StreamReader sr = new StreamReader(requestData);
62 string body = sr.ReadToEnd();
63 sr.Close();
64 body = body.Trim();
65
66 m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body);
67
68 try
69 {
70 lock (m_RequestLock)
71 {
72 Dictionary<string, object> request =
73 ServerUtils.ParseQueryString(body);
74
75 if (!request.ContainsKey("METHOD"))
76 return FailureResult();
77
78 string method = request["METHOD"].ToString();
79 request.Remove("METHOD");
80
81 try
82 {
83 m_EstateModule.InInfoUpdate = false;
84
85 switch (method)
86 {
87 case "update_covenant":
88 return UpdateCovenant(request);
89 case "update_estate":
90 return UpdateEstate(request);
91 case "estate_message":
92 return EstateMessage(request);
93 case "teleport_home_one_user":
94 return TeleportHomeOneUser(request);
95 case "teleport_home_all_users":
96 return TeleportHomeAllUsers(request);
97 }
98 }
99 finally
100 {
101 m_EstateModule.InInfoUpdate = false;
102 }
103 }
104 }
105 catch (Exception e)
106 {
107 m_log.Debug("[XESTATE]: Exception {0}" + e.ToString());
108 }
109
110 return FailureResult();
111 }
112
113 byte[] TeleportHomeAllUsers(Dictionary<string, object> request)
114 {
115 UUID PreyID = UUID.Zero;
116 int EstateID = 0;
117
118 if (!request.ContainsKey("EstateID"))
119 return FailureResult();
120
121 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
122 return FailureResult();
123
124 foreach (Scene s in m_EstateModule.Scenes)
125 {
126 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
127 {
128 s.ForEachScenePresence(delegate(ScenePresence p) {
129 if (p != null && !p.IsChildAgent)
130 {
131 p.ControllingClient.SendTeleportStart(16);
132 s.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient);
133 }
134 });
135 }
136 }
137
138 return SuccessResult();
139 }
140
141 byte[] TeleportHomeOneUser(Dictionary<string, object> request)
142 {
143 UUID PreyID = UUID.Zero;
144 int EstateID = 0;
145
146 if (!request.ContainsKey("PreyID") ||
147 !request.ContainsKey("EstateID"))
148 {
149 return FailureResult();
150 }
151
152 if (!UUID.TryParse(request["PreyID"].ToString(), out PreyID))
153 return FailureResult();
154
155 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
156 return FailureResult();
157
158 foreach (Scene s in m_EstateModule.Scenes)
159 {
160 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
161 {
162 ScenePresence p = s.GetScenePresence(PreyID);
163 if (p != null && !p.IsChildAgent)
164 {
165 p.ControllingClient.SendTeleportStart(16);
166 s.TeleportClientHome(PreyID, p.ControllingClient);
167 }
168 }
169 }
170
171 return SuccessResult();
172 }
173
174 byte[] EstateMessage(Dictionary<string, object> request)
175 {
176 UUID FromID = UUID.Zero;
177 string FromName = String.Empty;
178 string Message = String.Empty;
179 int EstateID = 0;
180
181 if (!request.ContainsKey("FromID") ||
182 !request.ContainsKey("FromName") ||
183 !request.ContainsKey("Message") ||
184 !request.ContainsKey("EstateID"))
185 {
186 return FailureResult();
187 }
188
189 if (!UUID.TryParse(request["FromID"].ToString(), out FromID))
190 return FailureResult();
191
192 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
193 return FailureResult();
194
195 FromName = request["FromName"].ToString();
196 Message = request["Message"].ToString();
197
198 foreach (Scene s in m_EstateModule.Scenes)
199 {
200 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
201 {
202 IDialogModule dm = s.RequestModuleInterface<IDialogModule>();
203
204 if (dm != null)
205 {
206 dm.SendNotificationToUsersInRegion(FromID, FromName,
207 Message);
208 }
209 }
210 }
211
212 return SuccessResult();
213 }
214
215 byte[] UpdateCovenant(Dictionary<string, object> request)
216 {
217 UUID CovenantID = UUID.Zero;
218 int EstateID = 0;
219
220 if (!request.ContainsKey("CovenantID") || !request.ContainsKey("EstateID"))
221 return FailureResult();
222
223 if (!UUID.TryParse(request["CovenantID"].ToString(), out CovenantID))
224 return FailureResult();
225
226 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
227 return FailureResult();
228
229 foreach (Scene s in m_EstateModule.Scenes)
230 {
231 if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID)
232 s.RegionInfo.RegionSettings.Covenant = CovenantID;
233 }
234
235 return SuccessResult();
236 }
237
238 byte[] UpdateEstate(Dictionary<string, object> request)
239 {
240 int EstateID = 0;
241
242 if (!request.ContainsKey("EstateID"))
243 return FailureResult();
244 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
245 return FailureResult();
246
247 foreach (Scene s in m_EstateModule.Scenes)
248 {
249 if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID)
250 s.ReloadEstateData();
251 }
252 return SuccessResult();
253 }
254
255 private byte[] FailureResult()
256 {
257 return BoolResult(false);
258 }
259
260 private byte[] SuccessResult()
261 {
262 return BoolResult(true);
263 }
264
265 private byte[] BoolResult(bool value)
266 {
267 XmlDocument doc = new XmlDocument();
268
269 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
270 "", "");
271
272 doc.AppendChild(xmlnode);
273
274 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
275 "");
276
277 doc.AppendChild(rootElement);
278
279 XmlElement result = doc.CreateElement("", "RESULT", "");
280 result.AppendChild(doc.CreateTextNode(value.ToString()));
281
282 rootElement.AppendChild(result);
283
284 return DocToBytes(doc);
285 }
286
287 private byte[] DocToBytes(XmlDocument doc)
288 {
289 MemoryStream ms = new MemoryStream();
290 XmlTextWriter xw = new XmlTextWriter(ms, null);
291 xw.Formatting = Formatting.Indented;
292 doc.WriteTo(xw);
293 xw.Flush();
294
295 return ms.ToArray();
296 }
297 }
298}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 73c592d..378826d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -40,23 +40,33 @@ namespace OpenSim.Region.CoreModules.World.Land
40 //Land types set with flags in ParcelOverlay. 40 //Land types set with flags in ParcelOverlay.
41 //Only one of these can be used. 41 //Only one of these can be used.
42 public const float BAN_LINE_SAFETY_HIEGHT = 100; 42 public const float BAN_LINE_SAFETY_HIEGHT = 100;
43 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000
44 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000
45 43
46 //RequestResults (I think these are right, they seem to work): 44 //RequestResults (I think these are right, they seem to work):
47 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land 45 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
48 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land 46 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
49 47
50 //ParcelSelectObjects 48 //ParcelSelectObjects
49 public const int LAND_SELECT_OBJECTS_OWNER = 2;
51 public const int LAND_SELECT_OBJECTS_GROUP = 4; 50 public const int LAND_SELECT_OBJECTS_GROUP = 4;
52 public const int LAND_SELECT_OBJECTS_OTHER = 8; 51 public const int LAND_SELECT_OBJECTS_OTHER = 8;
53 public const int LAND_SELECT_OBJECTS_OWNER = 2; 52
54 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 53
55 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 54 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
56 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 55 // types 1 to 7 are exclusive
57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 56 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
57 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
59 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 59 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
60 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
61 public const byte LAND_TYPE_unused6 = 6;
62 public const byte LAND_TYPE_unused7 = 7;
63 // next are flags
64 public const byte LAND_FLAG_unused8 = 0x08; // this may become excluside in future
65 public const byte LAND_FLAG_HIDEAVATARS = 0x10;
66 public const byte LAND_FLAG_LOCALSOUND = 0x20;
67 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 0x40; //Equals 01000000
68 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 0x80; //Equals 10000000
69
60 70
61 //These are other constants. Yay! 71 //These are other constants. Yay!
62 public const int START_LAND_LOCAL_ID = 1; 72 public const int START_LAND_LOCAL_ID = 1;
@@ -203,7 +213,13 @@ namespace OpenSim.Region.CoreModules.World.Land
203 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); 213 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
204 } 214 }
205 } 215 }
206 216 public void sendClientInitialLandInfo(IClientAPI remoteClient)
217 {
218 if (m_landManagementModule != null)
219 {
220 m_landManagementModule.sendClientInitialLandInfo(remoteClient);
221 }
222 }
207 #endregion 223 #endregion
208 } 224 }
209} 225}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 4e21724..c8555ab 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
46using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
@@ -70,10 +69,10 @@ namespace OpenSim.Region.CoreModules.World.Land
70 69
71 private LandChannel landChannel; 70 private LandChannel landChannel;
72 private Scene m_scene; 71 private Scene m_scene;
73 protected Commander m_commander = new Commander("land");
74 72
75 protected IUserManagement m_userManager; 73 protected IUserManagement m_userManager;
76 protected IPrimCountModule m_primCountModule; 74 protected IPrimCountModule m_primCountModule;
75 protected IDialogModule m_Dialog;
77 76
78 // Minimum for parcels to work is 64m even if we don't actually use them. 77 // Minimum for parcels to work is 64m even if we don't actually use them.
79 #pragma warning disable 0429 78 #pragma warning disable 0429
@@ -147,52 +146,33 @@ namespace OpenSim.Region.CoreModules.World.Land
147 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 146 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
148 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 147 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
149 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 148 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
150 m_scene.EventManager.OnPluginConsole += EventManagerOnPluginConsole; 149
151
152 lock (m_scene) 150 lock (m_scene)
153 { 151 {
154 m_scene.LandChannel = (ILandChannel)landChannel; 152 m_scene.LandChannel = (ILandChannel)landChannel;
155 } 153 }
156 154
157 InstallInterfaces(); 155 RegisterCommands();
158 } 156 }
159 157
160 public void RegionLoaded(Scene scene) 158 public void RegionLoaded(Scene scene)
161 { 159 {
162 m_userManager = m_scene.RequestModuleInterface<IUserManagement>(); 160 m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
163 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>(); 161 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
162 m_Dialog = m_scene.RequestModuleInterface<IDialogModule>();
164 } 163 }
165 164
166 public void RemoveRegion(Scene scene) 165 public void RemoveRegion(Scene scene)
167 { 166 {
168 // TODO: Also release other event manager listeners here 167 // TODO: Release event manager listeners here
169
170 m_scene.EventManager.OnPluginConsole -= EventManagerOnPluginConsole;
171 m_scene.UnregisterModuleCommander(m_commander.Name);
172 } 168 }
173 169
174 /// <summary> 170// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
175 /// Processes commandline input. Do not call directly. 171// {
176 /// </summary> 172// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
177 /// <param name="args">Commandline arguments</param> 173// reason = "You are not allowed to enter this sim.";
178 protected void EventManagerOnPluginConsole(string[] args) 174// return nearestParcel != null;
179 { 175// }
180 if (args[0] == "land")
181 {
182 if (args.Length == 1)
183 {
184 m_commander.ProcessConsoleCommand("help", new string[0]);
185 return;
186 }
187
188 string[] tmpArgs = new string[args.Length - 2];
189 int i;
190 for (i = 2; i < args.Length; i++)
191 tmpArgs[i - 2] = args[i];
192
193 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
194 }
195 }
196 176
197 void EventManagerOnNewClient(IClientAPI client) 177 void EventManagerOnNewClient(IClientAPI client)
198 { 178 {
@@ -213,13 +193,16 @@ namespace OpenSim.Region.CoreModules.World.Land
213 client.OnPreAgentUpdate += ClientOnPreAgentUpdate; 193 client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
214 client.OnParcelEjectUser += ClientOnParcelEjectUser; 194 client.OnParcelEjectUser += ClientOnParcelEjectUser;
215 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 195 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
196 client.OnSetStartLocationRequest += ClientOnSetHome;
216 197
198/* avatar is still a child here position is unknown
217 EntityBase presenceEntity; 199 EntityBase presenceEntity;
218 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 200 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
219 { 201 {
220 SendLandUpdate((ScenePresence)presenceEntity, true);
221 SendParcelOverlay(client); 202 SendParcelOverlay(client);
203 SendLandUpdate((ScenePresence)presenceEntity, true);
222 } 204 }
205*/
223 } 206 }
224 207
225 public void EventMakeChildAgent(ScenePresence avatar) 208 public void EventMakeChildAgent(ScenePresence avatar)
@@ -252,8 +235,7 @@ namespace OpenSim.Region.CoreModules.World.Land
252 public void UpdateLandObject(int local_id, LandData data) 235 public void UpdateLandObject(int local_id, LandData data)
253 { 236 {
254 LandData newData = data.Copy(); 237 LandData newData = data.Copy();
255 newData.LocalID = local_id; 238 newData.LocalID = local_id;
256 ILandObject landobj = null;
257 239
258 ILandObject land; 240 ILandObject land;
259 lock (m_landList) 241 lock (m_landList)
@@ -353,12 +335,13 @@ namespace OpenSim.Region.CoreModules.World.Land
353 if (!position.HasValue) 335 if (!position.HasValue)
354 return; 336 return;
355 337
356 bool isFlying = avatar.PhysicsActor.Flying; 338// land should have no word on avatar physics
357 avatar.RemoveFromPhysicalScene(); 339// bool isFlying = avatar.PhysicsActor.Flying;
340// avatar.RemoveFromPhysicalScene();
358 341
359 avatar.AbsolutePosition = (Vector3)position; 342 avatar.AbsolutePosition = (Vector3)position;
360 343
361 avatar.AddToPhysicalScene(isFlying); 344// avatar.AddToPhysicalScene(isFlying);
362 } 345 }
363 346
364 public void SendYouAreRestrictedNotice(ScenePresence avatar) 347 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -385,7 +368,7 @@ namespace OpenSim.Region.CoreModules.World.Land
385 public void SendOutNearestBanLine(IClientAPI client) 368 public void SendOutNearestBanLine(IClientAPI client)
386 { 369 {
387 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 370 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
388 if (sp == null || sp.IsChildAgent) 371 if (sp == null)
389 return; 372 return;
390 373
391 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); 374 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition);
@@ -405,42 +388,32 @@ namespace OpenSim.Region.CoreModules.World.Land
405 return; 388 return;
406 } 389 }
407 390
408 public void SendLandUpdate(ScenePresence avatar, bool force) 391 public void sendClientInitialLandInfo(IClientAPI remoteClient)
409 { 392 {
393 ScenePresence avatar;
410 394
411 /* stop sendind same data twice 395 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar))
412 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 396 return;
413 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
414 397
415 if (over != null) 398 SendParcelOverlay(remoteClient);
416 {
417 399
418 if (force) 400 if (avatar.IsChildAgent)
419 { 401 return;
420 if (!avatar.IsChildAgent)
421 {
422 over.SendLandUpdateToClient(avatar.ControllingClient);
423 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
424 m_scene.RegionInfo.RegionID);
425 }
426 }
427 402
428 if (avatar.currentParcelUUID != over.LandData.GlobalID) 403 ILandObject over = GetLandObject(avatar.AbsolutePosition.X,avatar.AbsolutePosition.Y);
429 { 404 if (over == null)
430 if (!avatar.IsChildAgent) 405 return;
431 { 406
432 over.SendLandUpdateToClient(avatar.ControllingClient); 407 avatar.currentParcelUUID = over.LandData.GlobalID;
433 avatar.currentParcelUUID = over.LandData.GlobalID; 408 over.SendLandUpdateToClient(avatar.ControllingClient);
434 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, 409 }
435 m_scene.RegionInfo.RegionID); 410
436 } 411 public void SendLandUpdate(ScenePresence avatar, bool force)
437 } 412 {
438 */
439 if (avatar.IsChildAgent) 413 if (avatar.IsChildAgent)
440 return; 414 return;
441 415
442 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 416 ILandObject over = GetLandObjectClipedXY(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
443 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
444 417
445 if (over != null) 418 if (over != null)
446 { 419 {
@@ -448,8 +421,8 @@ namespace OpenSim.Region.CoreModules.World.Land
448 if (force || NotsameID) 421 if (force || NotsameID)
449 { 422 {
450 over.SendLandUpdateToClient(avatar.ControllingClient); 423 over.SendLandUpdateToClient(avatar.ControllingClient);
451 if (NotsameID) 424 SendParcelOverlay(avatar.ControllingClient);
452 avatar.currentParcelUUID = over.LandData.GlobalID; 425 avatar.currentParcelUUID = over.LandData.GlobalID;
453 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, 426 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
454 m_scene.RegionInfo.RegionID); 427 m_scene.RegionInfo.RegionID);
455 } 428 }
@@ -759,6 +732,36 @@ namespace OpenSim.Region.CoreModules.World.Land
759 } 732 }
760 } 733 }
761 734
735 // if x,y is off region this will return the parcel at cliped x,y
736 // as did code it replaces
737 public ILandObject GetLandObjectClipedXY(float x, float y)
738 {
739 //do clip inline
740 int avx = (int)x;
741 if (avx < 0)
742 avx = 0;
743 else if (avx >= (int)Constants.RegionSize)
744 avx = (int)Constants.RegionSize - 1;
745
746 int avy = (int)y;
747 if (avy < 0)
748 avy = 0;
749 else if (avy >= (int)Constants.RegionSize)
750 avy = (int)Constants.RegionSize - 1;
751
752 lock (m_landIDList)
753 {
754 try
755 {
756 return m_landList[m_landIDList[avx / 4, avy / 4]];
757 }
758 catch (IndexOutOfRangeException)
759 {
760 return null;
761 }
762 }
763 }
764
762 public ILandObject GetLandObject(int x, int y) 765 public ILandObject GetLandObject(int x, int y)
763 { 766 {
764 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) 767 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
@@ -954,7 +957,9 @@ namespace OpenSim.Region.CoreModules.World.Land
954 //Now add the new land object 957 //Now add the new land object
955 ILandObject result = AddLandObject(newLand); 958 ILandObject result = AddLandObject(newLand);
956 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); 959 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
960 m_scene.ForEachClient(SendParcelOverlay);
957 result.SendLandUpdateToAvatarsOverMe(); 961 result.SendLandUpdateToAvatarsOverMe();
962 startLandObject.SendLandUpdateToAvatarsOverMe();
958 } 963 }
959 964
960 /// <summary> 965 /// <summary>
@@ -1018,6 +1023,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1018 } 1023 }
1019 } 1024 }
1020 1025
1026 m_scene.ForEachClient(SendParcelOverlay);
1021 masterLandObject.SendLandUpdateToAvatarsOverMe(); 1027 masterLandObject.SendLandUpdateToAvatarsOverMe();
1022 } 1028 }
1023 1029
@@ -1035,88 +1041,102 @@ namespace OpenSim.Region.CoreModules.World.Land
1035 1041
1036 #region Parcel Updating 1042 #region Parcel Updating
1037 1043
1044
1038 /// <summary> 1045 /// <summary>
1039 /// Where we send the ParcelOverlay packet to the client 1046 /// Where we send the ParcelOverlay packet to the client
1040 /// </summary> 1047 /// </summary>
1041 /// <param name="remote_client">The object representing the client</param> 1048 /// <param name="remote_client">The object representing the client</param>
1042 public void SendParcelOverlay(IClientAPI remote_client) 1049 public void SendParcelOverlay(IClientAPI remote_client)
1043 { 1050 {
1051 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
1052 return;
1053
1044 const int LAND_BLOCKS_PER_PACKET = 1024; 1054 const int LAND_BLOCKS_PER_PACKET = 1024;
1045 1055
1046 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1056 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1047 int byteArrayCount = 0; 1057 int byteArrayCount = 0;
1048 int sequenceID = 0; 1058 int sequenceID = 0;
1049 int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize;
1050 1059
1051 1060 for (int y = 0; y < Constants.RegionSize; y += 4)
1052 for (int y = 0; y < blockmeters; y++)
1053 { 1061 {
1054 for (int x = 0; x < blockmeters; x++) 1062 for (int x = 0; x < Constants.RegionSize; x += 4)
1055 { 1063 {
1056 byte tempByte = 0; //This represents the byte for the current 4x4 1064 byte tempByte = 0; //This represents the byte for the current 4x4
1057 1065
1058 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); 1066 ILandObject currentParcelBlock = GetLandObject(x, y);
1059 1067
1060 if (currentParcelBlock != null) 1068 if (currentParcelBlock != null)
1061 { 1069 {
1070 // types
1062 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1071 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1063 { 1072 {
1064 //Owner Flag 1073 //Owner Flag
1065 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1074 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER;
1066 } 1075 }
1067 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID)) 1076 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1068 { 1077 {
1069 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP); 1078 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP;
1070 } 1079 }
1071 else if (currentParcelBlock.LandData.SalePrice > 0 && 1080 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1072 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || 1081 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1073 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) 1082 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1074 { 1083 {
1075 //Sale Flag 1084 //Sale type
1076 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); 1085 tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE;
1077 } 1086 }
1078 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) 1087 else if(currentParcelBlock.LandData.OwnerID == UUID.Zero)
1079 { 1088 {
1080 //Public Flag 1089 //Public type
1081 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); 1090 tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero
1082 } 1091 }
1092// LAND_TYPE_IS_BEING_AUCTIONED still unsuported
1083 else 1093 else
1084 { 1094 {
1085 //Other Flag 1095 //Other Flag
1086 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); 1096 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER;
1087 } 1097 }
1088 1098
1089 //Now for border control 1099 // now flags
1100 // border control
1090 1101
1091 ILandObject westParcel = null; 1102 ILandObject westParcel = null;
1092 ILandObject southParcel = null; 1103 ILandObject southParcel = null;
1093 if (x > 0) 1104 if (x > 0)
1094 { 1105 {
1095 westParcel = GetLandObject((x - 1) * 4, y * 4); 1106 westParcel = GetLandObject((x - 1), y);
1096 } 1107 }
1097 if (y > 0) 1108 if (y > 0)
1098 { 1109 {
1099 southParcel = GetLandObject(x * 4, (y - 1) * 4); 1110 southParcel = GetLandObject(x, (y - 1));
1100 } 1111 }
1101 1112
1102 if (x == 0) 1113 if (x == 0)
1103 { 1114 {
1104 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1115 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1105 } 1116 }
1106 else if (westParcel != null && westParcel != currentParcelBlock) 1117 else if (westParcel != null && westParcel != currentParcelBlock)
1107 { 1118 {
1108 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1119 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1109 } 1120 }
1110 1121
1111 if (y == 0) 1122 if (y == 0)
1112 { 1123 {
1113 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1124 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1114 } 1125 }
1115 else if (southParcel != null && southParcel != currentParcelBlock) 1126 else if (southParcel != null && southParcel != currentParcelBlock)
1116 { 1127 {
1117 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1128 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1118 } 1129 }
1119 1130
1131 // local sound
1132 if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0)
1133 tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND;
1134
1135 // hide avatars
1136 if (!currentParcelBlock.LandData.SeeAVs)
1137 tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS;
1138
1139
1120 byteArray[byteArrayCount] = tempByte; 1140 byteArray[byteArrayCount] = tempByte;
1121 byteArrayCount++; 1141 byteArrayCount++;
1122 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) 1142 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
@@ -1169,7 +1189,44 @@ namespace OpenSim.Region.CoreModules.World.Land
1169 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 1189 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
1170 } 1190 }
1171 1191
1172 SendParcelOverlay(remote_client); 1192// SendParcelOverlay(remote_client);
1193 }
1194
1195 public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client)
1196 {
1197 bool snap_selection = false;
1198 bool needOverlay = false;
1199 if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay))
1200 {
1201 //the proprieties to who changed them
1202
1203 land.SendLandProperties(0, true, LandChannel.LAND_RESULT_SINGLE, remote_client);
1204
1205 if (needOverlay)
1206 {
1207 UUID parcelID = land.LandData.GlobalID;
1208 m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
1209 {
1210 if (avatar.IsDeleted || avatar.isNPC)
1211 return;
1212
1213 IClientAPI client = avatar.ControllingClient;
1214 SendParcelOverlay(client);
1215
1216 if (avatar.IsChildAgent)
1217 return;
1218
1219 ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
1220 if (aland != null)
1221 {
1222 if (client != remote_client || land != aland)
1223 aland.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, client);
1224 }
1225 if (avatar.currentParcelUUID == parcelID)
1226 avatar.currentParcelUUID = parcelID; // force parcel flags review
1227 });
1228 }
1229 }
1173 } 1230 }
1174 1231
1175 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) 1232 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
@@ -1182,7 +1239,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1182 1239
1183 if (land != null) 1240 if (land != null)
1184 { 1241 {
1185 land.UpdateLandProperties(args, remote_client); 1242 UpdateLandProperties(land, args, remote_client);
1186 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); 1243 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client);
1187 } 1244 }
1188 } 1245 }
@@ -1238,7 +1295,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1238 land.LandData.GroupID = UUID.Zero; 1295 land.LandData.GroupID = UUID.Zero;
1239 land.LandData.IsGroupOwned = false; 1296 land.LandData.IsGroupOwned = false;
1240 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1297 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1241
1242 m_scene.ForEachClient(SendParcelOverlay); 1298 m_scene.ForEachClient(SendParcelOverlay);
1243 land.SendLandUpdateToClient(true, remote_client); 1299 land.SendLandUpdateToClient(true, remote_client);
1244 } 1300 }
@@ -1286,7 +1342,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1286 land.LandData.SalePrice = 0; 1342 land.LandData.SalePrice = 0;
1287 land.LandData.AuthBuyerID = UUID.Zero; 1343 land.LandData.AuthBuyerID = UUID.Zero;
1288 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1344 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1289
1290 m_scene.ForEachClient(SendParcelOverlay); 1345 m_scene.ForEachClient(SendParcelOverlay);
1291 land.SendLandUpdateToClient(true, remote_client); 1346 land.SendLandUpdateToClient(true, remote_client);
1292 } 1347 }
@@ -1560,6 +1615,19 @@ namespace OpenSim.Region.CoreModules.World.Land
1560 land_update.ObscureMusic = properties.ObscureMusic; 1615 land_update.ObscureMusic = properties.ObscureMusic;
1561 land_update.ObscureMedia = properties.ObscureMedia; 1616 land_update.ObscureMedia = properties.ObscureMedia;
1562 1617
1618 if (args.ContainsKey("see_avs"))
1619 {
1620 land_update.SeeAVs = args["see_avs"].AsBoolean();
1621 land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean();
1622 land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean();
1623 }
1624 else
1625 {
1626 land_update.SeeAVs = true;
1627 land_update.AnyAVSounds = true;
1628 land_update.GroupAVSounds = true;
1629 }
1630
1563 ILandObject land; 1631 ILandObject land;
1564 lock (m_landList) 1632 lock (m_landList)
1565 { 1633 {
@@ -1568,13 +1636,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1568 1636
1569 if (land != null) 1637 if (land != null)
1570 { 1638 {
1571 land.UpdateLandProperties(land_update, client); 1639 UpdateLandProperties(land,land_update, client);
1572 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); 1640 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client);
1573 } 1641 }
1574 else 1642 else
1575 { 1643 {
1576 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); 1644 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
1577 } 1645 }
1646
1578 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1647 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1579 } 1648 }
1580 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the 1649 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
@@ -1896,52 +1965,139 @@ namespace OpenSim.Region.CoreModules.World.Land
1896 land.LandData.ParcelAccessList.Add(entry); 1965 land.LandData.ParcelAccessList.Add(entry);
1897 } 1966 }
1898 } 1967 }
1899 1968
1900 protected void InstallInterfaces() 1969 /// <summary>
1970 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
1971 /// </summary>
1972 /// <param name="remoteClient"></param>
1973 /// <param name="regionHandle"></param>
1974 /// <param name="position"></param>
1975 /// <param name="lookAt"></param>
1976 /// <param name="flags"></param>
1977 public virtual void ClientOnSetHome(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
1978 {
1979 // Let's find the parcel in question
1980 ILandObject land = landChannel.GetLandObject(position);
1981 if (land == null || m_scene.GridUserService == null)
1982 {
1983 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
1984 return;
1985 }
1986
1987 // Gather some data
1988 ulong gpowers = remoteClient.GetGroupPowers(land.LandData.GroupID);
1989 SceneObjectGroup telehub = null;
1990 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
1991 // Does the telehub exist in the scene?
1992 telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
1993
1994 // Can the user set home here?
1995 if (// (a) gods and land managers can set home
1996 m_scene.Permissions.IsAdministrator(remoteClient.AgentId) ||
1997 m_scene.Permissions.IsGod(remoteClient.AgentId) ||
1998 // (b) land owners can set home
1999 remoteClient.AgentId == land.LandData.OwnerID ||
2000 // (c) members of the land-associated group in roles that can set home
2001 ((gpowers & (ulong)GroupPowers.AllowSetHome) == (ulong)GroupPowers.AllowSetHome) ||
2002 // (d) parcels with telehubs can be the home of anyone
2003 (telehub != null && land.ContainsPoint((int)telehub.AbsolutePosition.X, (int)telehub.AbsolutePosition.Y)))
2004 {
2005 if (m_scene.GridUserService.SetHome(remoteClient.AgentId.ToString(), land.RegionUUID, position, lookAt))
2006 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2007 m_Dialog.SendAlertToUser(remoteClient, "Home position set.");
2008 else
2009 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
2010 }
2011 else
2012 m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel.");
2013 }
2014
2015 protected void RegisterCommands()
1901 { 2016 {
1902 Command clearCommand 2017 ICommands commands = MainConsole.Instance.Commands;
1903 = new Command("clear", CommandIntentions.COMMAND_HAZARDOUS, ClearCommand, "Clears all the parcels from the region.");
1904 Command showCommand
1905 = new Command("show", CommandIntentions.COMMAND_STATISTICAL, ShowParcelsCommand, "Shows all parcels on the region.");
1906 2018
1907 m_commander.RegisterCommand("clear", clearCommand); 2019 commands.AddCommand(
1908 m_commander.RegisterCommand("show", showCommand); 2020 "Land", false, "land clear",
2021 "land clear",
2022 "Clear all the parcels from the region.",
2023 "Command will ask for confirmation before proceeding.",
2024 HandleClearCommand);
1909 2025
1910 // Add this to our scene so scripts can call these functions 2026 commands.AddCommand(
1911 m_scene.RegisterModuleCommander(m_commander); 2027 "Land", false, "land show",
2028 "land show [<local-land-id>]",
2029 "Show information about the parcels on the region.",
2030 "If no local land ID is given, then summary information about all the parcels is shown.\n"
2031 + "If a local land ID is given then full information about that parcel is shown.",
2032 HandleShowCommand);
1912 } 2033 }
1913 2034
1914 protected void ClearCommand(Object[] args) 2035 protected void HandleClearCommand(string module, string[] args)
1915 { 2036 {
2037 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
2038 return;
2039
1916 string response = MainConsole.Instance.CmdPrompt( 2040 string response = MainConsole.Instance.CmdPrompt(
1917 string.Format( 2041 string.Format(
1918 "Are you sure that you want to clear all land parcels from {0} (y or n)", 2042 "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name),
1919 m_scene.RegionInfo.RegionName),
1920 "n"); 2043 "n");
1921 2044
1922 if (response.ToLower() == "y") 2045 if (response.ToLower() == "y")
1923 { 2046 {
1924 Clear(true); 2047 Clear(true);
1925 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.RegionInfo.RegionName); 2048 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.Name);
1926 } 2049 }
1927 else 2050 else
1928 { 2051 {
1929 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.RegionInfo.RegionName); 2052 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name);
1930 } 2053 }
1931 } 2054 }
1932 2055
1933 protected void ShowParcelsCommand(Object[] args) 2056 protected void HandleShowCommand(string module, string[] args)
1934 { 2057 {
1935 StringBuilder report = new StringBuilder(); 2058 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
1936 2059 return;
2060
2061 StringBuilder report = new StringBuilder();
2062
2063 if (args.Length <= 2)
2064 {
2065 AppendParcelsSummaryReport(report);
2066 }
2067 else
2068 {
2069 int landLocalId;
2070
2071 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId))
2072 return;
2073
2074 ILandObject lo;
2075
2076 lock (m_landList)
2077 {
2078 if (!m_landList.TryGetValue(landLocalId, out lo))
2079 {
2080 MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId);
2081 return;
2082 }
2083 }
2084
2085 AppendParcelReport(report, lo);
2086 }
2087
2088 MainConsole.Instance.Output(report.ToString());
2089 }
2090
2091 private void AppendParcelsSummaryReport(StringBuilder report)
2092 {
1937 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName); 2093 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName);
1938 report.AppendFormat( 2094 report.AppendFormat(
1939 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", 2095 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
1940 "Parcel Name", 2096 "Parcel Name",
1941 "Local ID", 2097 "Local ID",
1942 "Area", 2098 "Area",
1943 "Starts", 2099 "AABBMin",
1944 "Ends", 2100 "AABBMax",
1945 "Owner"); 2101 "Owner");
1946 2102
1947 lock (m_landList) 2103 lock (m_landList)
@@ -1952,11 +2108,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1952 2108
1953 report.AppendFormat( 2109 report.AppendFormat(
1954 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", 2110 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
1955 ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, m_userManager.GetUserName(ld.OwnerID)); 2111 ld.Name, ld.LocalID, ld.Area, ld.AABBMin, ld.AABBMax, m_userManager.GetUserName(ld.OwnerID));
1956 } 2112 }
1957 } 2113 }
1958 2114
1959 MainConsole.Instance.Output(report.ToString());
1960 } 2115 }
1961 2116
1962 public void EnforceBans(ILandObject land, ScenePresence avatar) 2117 public void EnforceBans(ILandObject land, ScenePresence avatar)
@@ -1979,6 +2134,67 @@ namespace OpenSim.Region.CoreModules.World.Land
1979 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition); 2134 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
1980 } 2135 }
1981 } 2136 }
2137 }
2138
2139 private void AppendParcelReport(StringBuilder report, ILandObject lo)
2140 {
2141 LandData ld = lo.LandData;
2142
2143 ConsoleDisplayList cdl = new ConsoleDisplayList();
2144 cdl.AddRow("Parcel name", ld.Name);
2145 cdl.AddRow("Local ID", ld.LocalID);
2146 cdl.AddRow("Description", ld.Description);
2147 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2148 cdl.AddRow("Area", ld.Area);
2149 cdl.AddRow("AABB Min", ld.AABBMin);
2150 cdl.AddRow("AABB Max", ld.AABBMax);
2151
2152 cdl.AddRow("Owner", m_userManager.GetUserName(ld.OwnerID));
2153 cdl.AddRow("Is group owned?", ld.IsGroupOwned);
2154 cdl.AddRow("GroupID", ld.GroupID);
2155
2156 cdl.AddRow("Status", ld.Status);
2157 cdl.AddRow("Flags", (ParcelFlags)ld.Flags);
2158
2159 cdl.AddRow("Landing Type", (LandingType)ld.LandingType);
2160 cdl.AddRow("User Location", ld.UserLocation);
2161 cdl.AddRow("User look at", ld.UserLookAt);
2162
2163 cdl.AddRow("Other clean time", ld.OtherCleanTime);
2164
2165 cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount());
2166 IPrimCounts pc = lo.PrimCounts;
2167 cdl.AddRow("Owner Prims", pc.Owner);
2168 cdl.AddRow("Group Prims", pc.Group);
2169 cdl.AddRow("Other Prims", pc.Others);
2170 cdl.AddRow("Selected Prims", pc.Selected);
2171 cdl.AddRow("Total Prims", pc.Total);
2172
2173 cdl.AddRow("Music URL", ld.MusicURL);
2174 cdl.AddRow("Obscure Music", ld.ObscureMusic);
2175
2176 cdl.AddRow("Media ID", ld.MediaID);
2177 cdl.AddRow("Media Autoscale", Convert.ToBoolean(ld.MediaAutoScale));
2178 cdl.AddRow("Media URL", ld.MediaURL);
2179 cdl.AddRow("Media Type", ld.MediaType);
2180 cdl.AddRow("Media Description", ld.MediaDescription);
2181 cdl.AddRow("Media Width", ld.MediaWidth);
2182 cdl.AddRow("Media Height", ld.MediaHeight);
2183 cdl.AddRow("Media Loop", ld.MediaLoop);
2184 cdl.AddRow("Obscure Media", ld.ObscureMedia);
2185
2186 cdl.AddRow("Parcel Category", ld.Category);
2187
2188 cdl.AddRow("Claim Date", ld.ClaimDate);
2189 cdl.AddRow("Claim Price", ld.ClaimPrice);
2190 cdl.AddRow("Pass Hours", ld.PassHours);
2191 cdl.AddRow("Pass Price", ld.PassPrice);
2192
2193 cdl.AddRow("Auction ID", ld.AuctionID);
2194 cdl.AddRow("Authorized Buyer ID", ld.AuthBuyerID);
2195 cdl.AddRow("Sale Price", ld.SalePrice);
2196
2197 cdl.AddToStringBuilder(report);
1982 } 2198 }
1983 } 2199 }
1984} 2200}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 2eafd44..e002feb 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -82,14 +82,14 @@ namespace OpenSim.Region.CoreModules.World.Land
82 82
83 set { m_landData = value; } 83 set { m_landData = value; }
84 } 84 }
85 85
86 public IPrimCounts PrimCounts { get; set; } 86 public IPrimCounts PrimCounts { get; set; }
87 87
88 public UUID RegionUUID 88 public UUID RegionUUID
89 { 89 {
90 get { return m_scene.RegionInfo.RegionID; } 90 get { return m_scene.RegionInfo.RegionID; }
91 } 91 }
92 92
93 public Vector3 StartPoint 93 public Vector3 StartPoint
94 { 94 {
95 get 95 get
@@ -102,11 +102,11 @@ namespace OpenSim.Region.CoreModules.World.Land
102 return new Vector3(x * 4, y * 4, 0); 102 return new Vector3(x * 4, y * 4, 0);
103 } 103 }
104 } 104 }
105 105
106 return new Vector3(-1, -1, -1); 106 return new Vector3(-1, -1, -1);
107 } 107 }
108 } 108 }
109 109
110 public Vector3 EndPoint 110 public Vector3 EndPoint
111 { 111 {
112 get 112 get
@@ -117,15 +117,15 @@ namespace OpenSim.Region.CoreModules.World.Land
117 { 117 {
118 if (LandBitmap[x, y]) 118 if (LandBitmap[x, y])
119 { 119 {
120 return new Vector3(x * 4, y * 4, 0); 120 return new Vector3(x * 4 + 4, y * 4 + 4, 0);
121 } 121 }
122 } 122 }
123 } 123 }
124 124
125 return new Vector3(-1, -1, -1); 125 return new Vector3(-1, -1, -1);
126 } 126 }
127 } 127 }
128 128
129 #region Constructors 129 #region Constructors
130 130
131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
@@ -244,18 +244,14 @@ namespace OpenSim.Region.CoreModules.World.Land
244 244
245 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 245 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
246 { 246 {
247 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
248 return;
249
247 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 250 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
248 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 251 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
249 if (estateModule != null) 252 if (estateModule != null)
250 regionFlags = estateModule.GetRegionFlags(); 253 regionFlags = estateModule.GetRegionFlags();
251 254
252 // In a perfect world, this would have worked.
253 //
254// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
255// regionFlags |= (uint)RegionFlags.AllowLandmark;
256// if (landData.OwnerID == remote_client.AgentId)
257// regionFlags |= (uint)RegionFlags.AllowSetHome;
258
259 int seq_id; 255 int seq_id;
260 if (snap_selection && (sequence_id == 0)) 256 if (snap_selection && (sequence_id == 0))
261 { 257 {
@@ -274,10 +270,11 @@ namespace OpenSim.Region.CoreModules.World.Land
274 GetSimulatorMaxPrimCount(), regionFlags); 270 GetSimulatorMaxPrimCount(), regionFlags);
275 } 271 }
276 272
277 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 273 public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
278 { 274 {
279 //Needs later group support 275 //Needs later group support
280 bool snap_selection = false; 276 snap_selection = false;
277 needOverlay = false;
281 LandData newData = LandData.Copy(); 278 LandData newData = LandData.Copy();
282 279
283 uint allowedDelta = 0; 280 uint allowedDelta = 0;
@@ -299,6 +296,9 @@ namespace OpenSim.Region.CoreModules.World.Land
299 ParcelFlags.AllowAPrimitiveEntry | 296 ParcelFlags.AllowAPrimitiveEntry |
300 ParcelFlags.AllowGroupObjectEntry | 297 ParcelFlags.AllowGroupObjectEntry |
301 ParcelFlags.AllowFly); 298 ParcelFlags.AllowFly);
299 newData.SeeAVs = args.SeeAVs;
300 newData.AnyAVSounds = args.AnyAVSounds;
301 newData.GroupAVSounds = args.GroupAVSounds;
302 } 302 }
303 303
304 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true)) 304 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
@@ -394,9 +394,16 @@ namespace OpenSim.Region.CoreModules.World.Land
394 uint preserve = LandData.Flags & ~allowedDelta; 394 uint preserve = LandData.Flags & ~allowedDelta;
395 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 395 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
396 396
397 uint curdelta = LandData.Flags ^ newData.Flags;
398 curdelta &= (uint)(ParcelFlags.SoundLocal);
399
400 if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
401 needOverlay = true;
402
397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 403 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
398 SendLandUpdateToAvatarsOverMe(snap_selection); 404 return true;
399 } 405 }
406 return false;
400 } 407 }
401 408
402 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 409 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -412,7 +419,7 @@ namespace OpenSim.Region.CoreModules.World.Land
412 newData.AuthBuyerID = UUID.Zero; 419 newData.AuthBuyerID = UUID.Zero;
413 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 420 newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
414 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 421 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
415 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 422// m_scene.EventManager.TriggerParcelPrimCountUpdate();
416 SendLandUpdateToAvatarsOverMe(true); 423 SendLandUpdateToAvatarsOverMe(true);
417 } 424 }
418 425
@@ -583,6 +590,7 @@ namespace OpenSim.Region.CoreModules.World.Land
583 590
584 public void SendLandUpdateToAvatarsOverMe(bool snap_selection) 591 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
585 { 592 {
593 m_scene.EventManager.TriggerParcelPrimCountUpdate();
586 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 594 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
587 { 595 {
588 ILandObject over = null; 596 ILandObject over = null;
@@ -609,6 +617,7 @@ namespace OpenSim.Region.CoreModules.World.Land
609 avatar.Invulnerable = true; 617 avatar.Invulnerable = true;
610 618
611 SendLandUpdateToClient(snap_selection, avatar.ControllingClient); 619 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
620 avatar.currentParcelUUID = LandData.GlobalID;
612 } 621 }
613 } 622 }
614 }); 623 });
@@ -737,10 +746,10 @@ namespace OpenSim.Region.CoreModules.World.Land
737 /// </summary> 746 /// </summary>
738 private void UpdateAABBAndAreaValues() 747 private void UpdateAABBAndAreaValues()
739 { 748 {
740 int min_x = 64; 749 int min_x = Int32.MaxValue;
741 int min_y = 64; 750 int min_y = Int32.MaxValue;
742 int max_x = 0; 751 int max_x = Int32.MinValue;
743 int max_y = 0; 752 int max_y = Int32.MinValue;
744 int tempArea = 0; 753 int tempArea = 0;
745 int x, y; 754 int x, y;
746 for (x = 0; x < 64; x++) 755 for (x = 0; x < 64; x++)
@@ -749,35 +758,56 @@ namespace OpenSim.Region.CoreModules.World.Land
749 { 758 {
750 if (LandBitmap[x, y] == true) 759 if (LandBitmap[x, y] == true)
751 { 760 {
752 if (min_x > x) min_x = x; 761 if (min_x > x)
753 if (min_y > y) min_y = y; 762 min_x = x;
754 if (max_x < x) max_x = x; 763 if (min_y > y)
755 if (max_y < y) max_y = y; 764 min_y = y;
765 if (max_x < x)
766 max_x = x;
767 if (max_y < y)
768 max_y = y;
756 tempArea += 16; //16sqm peice of land 769 tempArea += 16; //16sqm peice of land
757 } 770 }
758 } 771 }
759 } 772 }
773
760 int tx = min_x * 4; 774 int tx = min_x * 4;
761 if (tx > ((int)Constants.RegionSize - 1)) 775 int htx;
762 tx = ((int)Constants.RegionSize - 1); 776 if (tx == ((int)Constants.RegionSize))
777 htx = tx - 1;
778 else
779 htx = tx;
780
763 int ty = min_y * 4; 781 int ty = min_y * 4;
764 if (ty > ((int)Constants.RegionSize - 1)) 782 int hty;
765 ty = ((int)Constants.RegionSize - 1); 783
784 if (ty == ((int)Constants.RegionSize))
785 hty = ty - 1;
786 else
787 hty = ty;
766 788
767 LandData.AABBMin = 789 LandData.AABBMin =
768 new Vector3( 790 new Vector3(
769 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 791 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
770 792
793 max_x++;
771 tx = max_x * 4; 794 tx = max_x * 4;
772 if (tx > ((int)Constants.RegionSize - 1)) 795 if (tx == ((int)Constants.RegionSize))
773 tx = ((int)Constants.RegionSize - 1); 796 htx = tx - 1;
797 else
798 htx = tx;
799
800 max_y++;
774 ty = max_y * 4; 801 ty = max_y * 4;
775 if (ty > ((int)Constants.RegionSize - 1)) 802
776 ty = ((int)Constants.RegionSize - 1); 803 if (ty == ((int)Constants.RegionSize))
804 hty = ty - 1;
805 else
806 hty = ty;
777 807
778 LandData.AABBMax 808 LandData.AABBMax
779 = new Vector3( 809 = new Vector3(
780 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 810 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
781 811
782 LandData.Area = tempArea; 812 LandData.Area = tempArea;
783 } 813 }
@@ -902,13 +932,31 @@ namespace OpenSim.Region.CoreModules.World.Land
902 private byte[] ConvertLandBitmapToBytes() 932 private byte[] ConvertLandBitmapToBytes()
903 { 933 {
904 byte[] tempConvertArr = new byte[512]; 934 byte[] tempConvertArr = new byte[512];
905 byte tempByte = 0; 935 int tempByte = 0;
906 int x, y, i, byteNum = 0; 936 int x, y, i, byteNum = 0;
937 int mask = 1;
907 i = 0; 938 i = 0;
908 for (y = 0; y < 64; y++) 939 for (y = 0; y < 64; y++)
909 { 940 {
910 for (x = 0; x < 64; x++) 941 for (x = 0; x < 64; x++)
911 { 942 {
943 if (LandBitmap[x, y])
944 tempByte |= mask;
945 mask = mask << 1;
946 if (mask == 0x100)
947 {
948 mask = 1;
949 tempConvertArr[byteNum++] = (byte)tempByte;
950 tempByte = 0;
951 }
952 }
953 }
954
955 if(tempByte != 0 && byteNum < 512)
956 tempConvertArr[byteNum] = (byte)tempByte;
957
958
959/*
912 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 960 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
913 if (i % 8 == 0) 961 if (i % 8 == 0)
914 { 962 {
@@ -917,8 +965,7 @@ namespace OpenSim.Region.CoreModules.World.Land
917 i = 0; 965 i = 0;
918 byteNum++; 966 byteNum++;
919 } 967 }
920 } 968 */
921 }
922 return tempConvertArr; 969 return tempConvertArr;
923 } 970 }
924 971
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 40638f8..bc52a43 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
55 public struct DrawStruct 55 public struct DrawStruct
56 { 56 {
57 public DrawRoutine dr; 57 public DrawRoutine dr;
58 public Rectangle rect; 58// public Rectangle rect;
59 public SolidBrush brush; 59 public SolidBrush brush;
60 public face[] trns; 60 public face[] trns;
61 } 61 }
@@ -119,6 +119,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
119 { 119 {
120 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); 120 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID);
121 } 121 }
122
122 return mapbmp; 123 return mapbmp;
123 } 124 }
124 125
@@ -127,7 +128,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
127 try 128 try
128 { 129 {
129 using (Bitmap mapbmp = CreateMapTile()) 130 using (Bitmap mapbmp = CreateMapTile())
130 return OpenJPEG.EncodeFromImage(mapbmp, true); 131 {
132 if (mapbmp != null)
133 return OpenJPEG.EncodeFromImage(mapbmp, true);
134 }
131 } 135 }
132 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 136 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
133 { 137 {
@@ -277,321 +281,331 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
277 tc = Environment.TickCount; 281 tc = Environment.TickCount;
278 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); 282 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
279 EntityBase[] objs = whichScene.GetEntities(); 283 EntityBase[] objs = whichScene.GetEntities();
280 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
281 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
282 List<float> z_sortheights = new List<float>(); 284 List<float> z_sortheights = new List<float>();
283 List<uint> z_localIDs = new List<uint>(); 285 List<uint> z_localIDs = new List<uint>();
286 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
284 287
285 lock (objs) 288 try
286 { 289 {
287 foreach (EntityBase obj in objs) 290 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
291
292 lock (objs)
288 { 293 {
289 // Only draw the contents of SceneObjectGroup 294 foreach (EntityBase obj in objs)
290 if (obj is SceneObjectGroup)
291 { 295 {
292 SceneObjectGroup mapdot = (SceneObjectGroup)obj; 296 // Only draw the contents of SceneObjectGroup
293 Color mapdotspot = Color.Gray; // Default color when prim color is white 297 if (obj is SceneObjectGroup)
294
295 // Loop over prim in group
296 foreach (SceneObjectPart part in mapdot.Parts)
297 { 298 {
298 if (part == null) 299 SceneObjectGroup mapdot = (SceneObjectGroup)obj;
299 continue; 300 Color mapdotspot = Color.Gray; // Default color when prim color is white
300 301
301 // Draw if the object is at least 1 meter wide in any direction 302 // Loop over prim in group
302 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) 303 foreach (SceneObjectPart part in mapdot.Parts)
303 { 304 {
304 // Try to get the RGBA of the default texture entry.. 305 if (part == null)
305 // 306 continue;
306 try 307
308 // Draw if the object is at least 1 meter wide in any direction
309 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
307 { 310 {
308 // get the null checks out of the way 311 // Try to get the RGBA of the default texture entry..
309 // skip the ones that break 312 //
310 if (part == null) 313 try
311 continue; 314 {
315 // get the null checks out of the way
316 // skip the ones that break
317 if (part == null)
318 continue;
312 319
313 if (part.Shape == null) 320 if (part.Shape == null)
314 continue; 321 continue;
315 322
316 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) 323 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
317 continue; // eliminates trees from this since we don't really have a good tree representation 324 continue; // eliminates trees from this since we don't really have a good tree representation
318 // if you want tree blocks on the map comment the above line and uncomment the below line 325 // if you want tree blocks on the map comment the above line and uncomment the below line
319 //mapdotspot = Color.PaleGreen; 326 //mapdotspot = Color.PaleGreen;
320 327
321 Primitive.TextureEntry textureEntry = part.Shape.Textures; 328 Primitive.TextureEntry textureEntry = part.Shape.Textures;
322 329
323 if (textureEntry == null || textureEntry.DefaultTexture == null) 330 if (textureEntry == null || textureEntry.DefaultTexture == null)
324 continue; 331 continue;
325 332
326 Color4 texcolor = textureEntry.DefaultTexture.RGBA; 333 Color4 texcolor = textureEntry.DefaultTexture.RGBA;
327 334
328 // Not sure why some of these are null, oh well. 335 // Not sure why some of these are null, oh well.
329 336
330 int colorr = 255 - (int)(texcolor.R * 255f); 337 int colorr = 255 - (int)(texcolor.R * 255f);
331 int colorg = 255 - (int)(texcolor.G * 255f); 338 int colorg = 255 - (int)(texcolor.G * 255f);
332 int colorb = 255 - (int)(texcolor.B * 255f); 339 int colorb = 255 - (int)(texcolor.B * 255f);
333 340
334 if (!(colorr == 255 && colorg == 255 && colorb == 255)) 341 if (!(colorr == 255 && colorg == 255 && colorb == 255))
335 {
336 //Try to set the map spot color
337 try
338 {
339 // If the color gets goofy somehow, skip it *shakes fist at Color4
340 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
341 }
342 catch (ArgumentException)
343 { 342 {
343 //Try to set the map spot color
344 try
345 {
346 // If the color gets goofy somehow, skip it *shakes fist at Color4
347 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
348 }
349 catch (ArgumentException)
350 {
351 }
344 } 352 }
345 } 353 }
346 } 354 catch (IndexOutOfRangeException)
347 catch (IndexOutOfRangeException) 355 {
348 { 356 // Windows Array
349 // Windows Array 357 }
350 } 358 catch (ArgumentOutOfRangeException)
351 catch (ArgumentOutOfRangeException) 359 {
352 { 360 // Mono Array
353 // Mono Array 361 }
354 }
355
356 Vector3 pos = part.GetWorldPosition();
357
358 // skip prim outside of retion
359 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
360 continue;
361
362 // skip prim in non-finite position
363 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
364 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
365 continue;
366
367 // Figure out if object is under 256m above the height of the terrain
368 bool isBelow256AboveTerrain = false;
369 362
370 try 363 Vector3 pos = part.GetWorldPosition();
371 {
372 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
373 }
374 catch (Exception)
375 {
376 }
377 364
378 if (isBelow256AboveTerrain) 365 // skip prim outside of retion
379 { 366 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
380 // Translate scale by rotation so scale is represented properly when object is rotated
381 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
382 Vector3 scale = new Vector3();
383 Vector3 tScale = new Vector3();
384 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
385
386 Quaternion llrot = part.GetWorldRotation();
387 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
388 scale = lscale * rot;
389
390 // negative scales don't work in this situation
391 scale.X = Math.Abs(scale.X);
392 scale.Y = Math.Abs(scale.Y);
393 scale.Z = Math.Abs(scale.Z);
394
395 // This scaling isn't very accurate and doesn't take into account the face rotation :P
396 int mapdrawstartX = (int)(pos.X - scale.X);
397 int mapdrawstartY = (int)(pos.Y - scale.Y);
398 int mapdrawendX = (int)(pos.X + scale.X);
399 int mapdrawendY = (int)(pos.Y + scale.Y);
400
401 // If object is beyond the edge of the map, don't draw it to avoid errors
402 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
403 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
404 || mapdrawendY > ((int)Constants.RegionSize - 1))
405 continue; 367 continue;
406 368
407#region obb face reconstruction part duex 369 // skip prim in non-finite position
408 Vector3[] vertexes = new Vector3[8]; 370 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
409 371 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
410 // float[] distance = new float[6]; 372 continue;
411 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
412 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
413 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
414 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
415
416 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
417 scale = ((tScale * rot));
418 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
419 // vertexes[0].x = pos.X + vertexes[0].x;
420 //vertexes[0].y = pos.Y + vertexes[0].y;
421 //vertexes[0].z = pos.Z + vertexes[0].z;
422
423 FaceA[0] = vertexes[0];
424 FaceB[3] = vertexes[0];
425 FaceA[4] = vertexes[0];
426
427 tScale = lscale;
428 scale = ((tScale * rot));
429 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
430
431 // vertexes[1].x = pos.X + vertexes[1].x;
432 // vertexes[1].y = pos.Y + vertexes[1].y;
433 //vertexes[1].z = pos.Z + vertexes[1].z;
434
435 FaceB[0] = vertexes[1];
436 FaceA[1] = vertexes[1];
437 FaceC[4] = vertexes[1];
438
439 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
440 scale = ((tScale * rot));
441
442 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
443
444 //vertexes[2].x = pos.X + vertexes[2].x;
445 //vertexes[2].y = pos.Y + vertexes[2].y;
446 //vertexes[2].z = pos.Z + vertexes[2].z;
447
448 FaceC[0] = vertexes[2];
449 FaceD[3] = vertexes[2];
450 FaceC[5] = vertexes[2];
451
452 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
453 scale = ((tScale * rot));
454 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
455
456 //vertexes[3].x = pos.X + vertexes[3].x;
457 // vertexes[3].y = pos.Y + vertexes[3].y;
458 // vertexes[3].z = pos.Z + vertexes[3].z;
459
460 FaceD[0] = vertexes[3];
461 FaceC[1] = vertexes[3];
462 FaceA[5] = vertexes[3];
463
464 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
465 scale = ((tScale * rot));
466 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
467
468 // vertexes[4].x = pos.X + vertexes[4].x;
469 // vertexes[4].y = pos.Y + vertexes[4].y;
470 // vertexes[4].z = pos.Z + vertexes[4].z;
471
472 FaceB[1] = vertexes[4];
473 FaceA[2] = vertexes[4];
474 FaceD[4] = vertexes[4];
475
476 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
477 scale = ((tScale * rot));
478 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
479
480 // vertexes[5].x = pos.X + vertexes[5].x;
481 // vertexes[5].y = pos.Y + vertexes[5].y;
482 // vertexes[5].z = pos.Z + vertexes[5].z;
483
484 FaceD[1] = vertexes[5];
485 FaceC[2] = vertexes[5];
486 FaceB[5] = vertexes[5];
487 373
488 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); 374 // Figure out if object is under 256m above the height of the terrain
489 scale = ((tScale * rot)); 375 bool isBelow256AboveTerrain = false;
490 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
491 376
492 // vertexes[6].x = pos.X + vertexes[6].x; 377 try
493 // vertexes[6].y = pos.Y + vertexes[6].y; 378 {
494 // vertexes[6].z = pos.Z + vertexes[6].z; 379 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
380 }
381 catch (Exception)
382 {
383 }
495 384
496 FaceB[2] = vertexes[6]; 385 if (isBelow256AboveTerrain)
497 FaceA[3] = vertexes[6]; 386 {
498 FaceB[4] = vertexes[6]; 387 // Translate scale by rotation so scale is represented properly when object is rotated
388 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
389 Vector3 scale = new Vector3();
390 Vector3 tScale = new Vector3();
391 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
392
393 Quaternion llrot = part.GetWorldRotation();
394 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
395 scale = lscale * rot;
396
397 // negative scales don't work in this situation
398 scale.X = Math.Abs(scale.X);
399 scale.Y = Math.Abs(scale.Y);
400 scale.Z = Math.Abs(scale.Z);
401
402 // This scaling isn't very accurate and doesn't take into account the face rotation :P
403 int mapdrawstartX = (int)(pos.X - scale.X);
404 int mapdrawstartY = (int)(pos.Y - scale.Y);
405 int mapdrawendX = (int)(pos.X + scale.X);
406 int mapdrawendY = (int)(pos.Y + scale.Y);
407
408 // If object is beyond the edge of the map, don't draw it to avoid errors
409 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
410 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
411 || mapdrawendY > ((int)Constants.RegionSize - 1))
412 continue;
413
414 #region obb face reconstruction part duex
415 Vector3[] vertexes = new Vector3[8];
416
417 // float[] distance = new float[6];
418 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
419 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
420 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
421 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
422
423 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
424 scale = ((tScale * rot));
425 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
426 // vertexes[0].x = pos.X + vertexes[0].x;
427 //vertexes[0].y = pos.Y + vertexes[0].y;
428 //vertexes[0].z = pos.Z + vertexes[0].z;
429
430 FaceA[0] = vertexes[0];
431 FaceB[3] = vertexes[0];
432 FaceA[4] = vertexes[0];
433
434 tScale = lscale;
435 scale = ((tScale * rot));
436 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
437
438 // vertexes[1].x = pos.X + vertexes[1].x;
439 // vertexes[1].y = pos.Y + vertexes[1].y;
440 //vertexes[1].z = pos.Z + vertexes[1].z;
441
442 FaceB[0] = vertexes[1];
443 FaceA[1] = vertexes[1];
444 FaceC[4] = vertexes[1];
445
446 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
447 scale = ((tScale * rot));
448
449 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
450
451 //vertexes[2].x = pos.X + vertexes[2].x;
452 //vertexes[2].y = pos.Y + vertexes[2].y;
453 //vertexes[2].z = pos.Z + vertexes[2].z;
454
455 FaceC[0] = vertexes[2];
456 FaceD[3] = vertexes[2];
457 FaceC[5] = vertexes[2];
458
459 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
460 scale = ((tScale * rot));
461 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
462
463 //vertexes[3].x = pos.X + vertexes[3].x;
464 // vertexes[3].y = pos.Y + vertexes[3].y;
465 // vertexes[3].z = pos.Z + vertexes[3].z;
466
467 FaceD[0] = vertexes[3];
468 FaceC[1] = vertexes[3];
469 FaceA[5] = vertexes[3];
470
471 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
472 scale = ((tScale * rot));
473 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
474
475 // vertexes[4].x = pos.X + vertexes[4].x;
476 // vertexes[4].y = pos.Y + vertexes[4].y;
477 // vertexes[4].z = pos.Z + vertexes[4].z;
478
479 FaceB[1] = vertexes[4];
480 FaceA[2] = vertexes[4];
481 FaceD[4] = vertexes[4];
482
483 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
484 scale = ((tScale * rot));
485 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
486
487 // vertexes[5].x = pos.X + vertexes[5].x;
488 // vertexes[5].y = pos.Y + vertexes[5].y;
489 // vertexes[5].z = pos.Z + vertexes[5].z;
490
491 FaceD[1] = vertexes[5];
492 FaceC[2] = vertexes[5];
493 FaceB[5] = vertexes[5];
494
495 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
496 scale = ((tScale * rot));
497 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
498
499 // vertexes[6].x = pos.X + vertexes[6].x;
500 // vertexes[6].y = pos.Y + vertexes[6].y;
501 // vertexes[6].z = pos.Z + vertexes[6].z;
502
503 FaceB[2] = vertexes[6];
504 FaceA[3] = vertexes[6];
505 FaceB[4] = vertexes[6];
499 506
500 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); 507 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
501 scale = ((tScale * rot)); 508 scale = ((tScale * rot));
502 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); 509 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
503 510
504 // vertexes[7].x = pos.X + vertexes[7].x; 511 // vertexes[7].x = pos.X + vertexes[7].x;
505 // vertexes[7].y = pos.Y + vertexes[7].y; 512 // vertexes[7].y = pos.Y + vertexes[7].y;
506 // vertexes[7].z = pos.Z + vertexes[7].z; 513 // vertexes[7].z = pos.Z + vertexes[7].z;
507 514
508 FaceD[2] = vertexes[7]; 515 FaceD[2] = vertexes[7];
509 FaceC[3] = vertexes[7]; 516 FaceC[3] = vertexes[7];
510 FaceD[5] = vertexes[7]; 517 FaceD[5] = vertexes[7];
511#endregion 518 #endregion
512 519
513 //int wy = 0; 520 //int wy = 0;
514 521
515 //bool breakYN = false; // If we run into an error drawing, break out of the 522 //bool breakYN = false; // If we run into an error drawing, break out of the
516 // loop so we don't lag to death on error handling 523 // loop so we don't lag to death on error handling
517 DrawStruct ds = new DrawStruct(); 524 DrawStruct ds = new DrawStruct();
518 ds.brush = new SolidBrush(mapdotspot); 525 ds.brush = new SolidBrush(mapdotspot);
519 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); 526 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
520 527
521 ds.trns = new face[FaceA.Length]; 528 ds.trns = new face[FaceA.Length];
522 529
523 for (int i = 0; i < FaceA.Length; i++) 530 for (int i = 0; i < FaceA.Length; i++)
524 { 531 {
525 Point[] working = new Point[5]; 532 Point[] working = new Point[5];
526 working[0] = project(FaceA[i], axPos); 533 working[0] = project(FaceA[i], axPos);
527 working[1] = project(FaceB[i], axPos); 534 working[1] = project(FaceB[i], axPos);
528 working[2] = project(FaceD[i], axPos); 535 working[2] = project(FaceD[i], axPos);
529 working[3] = project(FaceC[i], axPos); 536 working[3] = project(FaceC[i], axPos);
530 working[4] = project(FaceA[i], axPos); 537 working[4] = project(FaceA[i], axPos);
531 538
532 face workingface = new face(); 539 face workingface = new face();
533 workingface.pts = working; 540 workingface.pts = working;
534 541
535 ds.trns[i] = workingface; 542 ds.trns[i] = workingface;
536 } 543 }
537 544
538 z_sort.Add(part.LocalId, ds); 545 z_sort.Add(part.LocalId, ds);
539 z_localIDs.Add(part.LocalId); 546 z_localIDs.Add(part.LocalId);
540 z_sortheights.Add(pos.Z); 547 z_sortheights.Add(pos.Z);
541 548
542 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) 549 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
543 //{
544 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
545 //{ 550 //{
546 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); 551 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
547 //try
548 //{
549 // Remember, flip the y!
550 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
551 //}
552 //catch (ArgumentException)
553 //{ 552 //{
554 // breakYN = true; 553 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
554 //try
555 //{
556 // Remember, flip the y!
557 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
558 //}
559 //catch (ArgumentException)
560 //{
561 // breakYN = true;
562 //}
563
564 //if (breakYN)
565 // break;
555 //} 566 //}
556 567
557 //if (breakYN) 568 //if (breakYN)
558 // break; 569 // break;
559 //} 570 //}
571 } // Object is within 256m Z of terrain
572 } // object is at least a meter wide
573 } // loop over group children
574 } // entitybase is sceneobject group
575 } // foreach loop over entities
560 576
561 //if (breakYN) 577 float[] sortedZHeights = z_sortheights.ToArray();
562 // break; 578 uint[] sortedlocalIds = z_localIDs.ToArray();
563 //}
564 } // Object is within 256m Z of terrain
565 } // object is at least a meter wide
566 } // loop over group children
567 } // entitybase is sceneobject group
568 } // foreach loop over entities
569
570 float[] sortedZHeights = z_sortheights.ToArray();
571 uint[] sortedlocalIds = z_localIDs.ToArray();
572
573 // Sort prim by Z position
574 Array.Sort(sortedZHeights, sortedlocalIds);
575 579
576 Graphics g = Graphics.FromImage(mapbmp); 580 // Sort prim by Z position
581 Array.Sort(sortedZHeights, sortedlocalIds);
577 582
578 for (int s = 0; s < sortedZHeights.Length; s++) 583 using (Graphics g = Graphics.FromImage(mapbmp))
579 {
580 if (z_sort.ContainsKey(sortedlocalIds[s]))
581 { 584 {
582 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; 585 for (int s = 0; s < sortedZHeights.Length; s++)
583 for (int r = 0; r < rectDrawStruct.trns.Length; r++)
584 { 586 {
585 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); 587 if (z_sort.ContainsKey(sortedlocalIds[s]))
588 {
589 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]];
590 for (int r = 0; r < rectDrawStruct.trns.Length; r++)
591 {
592 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts);
593 }
594 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
595 }
586 } 596 }
587 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
588 } 597 }
589 } 598 } // lock entities objs
590 599
591 g.Dispose(); 600 }
592 } // lock entities objs 601 finally
602 {
603 foreach (DrawStruct ds in z_sort.Values)
604 ds.brush.Dispose();
605 }
593 606
594 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); 607 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms");
608
595 return mapbmp; 609 return mapbmp;
596 } 610 }
597 611
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index 992bff3..cb06fd4 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
54 public void TerrainToBitmap(Bitmap mapbmp) 54 public void TerrainToBitmap(Bitmap mapbmp)
55 { 55 {
56 int tc = Environment.TickCount; 56 int tc = Environment.TickCount;
57 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 57 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
58 58
59 double[,] hm = m_scene.Heightmap.GetDoubles(); 59 double[,] hm = m_scene.Heightmap.GetDoubles();
60 bool ShadowDebugContinue = true; 60 bool ShadowDebugContinue = true;
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
199 { 199 {
200 if (!terraincorruptedwarningsaid) 200 if (!terraincorruptedwarningsaid)
201 { 201 {
202 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); 202 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
203 terraincorruptedwarningsaid = true; 203 terraincorruptedwarningsaid = true;
204 } 204 }
205 color = Color.Black; 205 color = Color.Black;
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
229 { 229 {
230 if (!terraincorruptedwarningsaid) 230 if (!terraincorruptedwarningsaid)
231 { 231 {
232 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); 232 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
233 terraincorruptedwarningsaid = true; 233 terraincorruptedwarningsaid = true;
234 } 234 }
235 Color black = Color.Black; 235 Color black = Color.Black;
@@ -238,7 +238,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
238 } 238 }
239 } 239 }
240 } 240 }
241 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 241
242 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
242 } 243 }
243 } 244 }
244} 245} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index d13c2ef..e895178 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
173 private Bitmap fetchTexture(UUID id) 173 private Bitmap fetchTexture(UUID id)
174 { 174 {
175 AssetBase asset = m_scene.AssetService.Get(id.ToString()); 175 AssetBase asset = m_scene.AssetService.Get(id.ToString());
176 m_log.DebugFormat("[TexturedMapTileRenderer]: Fetched texture {0}, found: {1}", id, asset != null); 176 m_log.DebugFormat("[TEXTURED MAP TILE RENDERER]: Fetched texture {0}, found: {1}", id, asset != null);
177 if (asset == null) return null; 177 if (asset == null) return null;
178 178
179 ManagedImage managedImage; 179 ManagedImage managedImage;
@@ -188,17 +188,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
188 } 188 }
189 catch (DllNotFoundException) 189 catch (DllNotFoundException)
190 { 190 {
191 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); 191 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
192 192
193 } 193 }
194 catch (IndexOutOfRangeException) 194 catch (IndexOutOfRangeException)
195 { 195 {
196 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 196 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
197 197
198 } 198 }
199 catch (Exception) 199 catch (Exception)
200 { 200 {
201 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 201 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
202 202
203 } 203 }
204 return null; 204 return null;
@@ -233,10 +233,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
233 if (textureID == UUID.Zero) return defaultColor; // not set 233 if (textureID == UUID.Zero) return defaultColor; // not set
234 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures 234 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures
235 235
236 Bitmap bmp = fetchTexture(textureID); 236 Color color;
237 Color color = bmp == null ? defaultColor : computeAverageColor(bmp); 237
238 // store it for future reference 238 using (Bitmap bmp = fetchTexture(textureID))
239 m_mapping[textureID] = color; 239 {
240 color = bmp == null ? defaultColor : computeAverageColor(bmp);
241 // store it for future reference
242 m_mapping[textureID] = color;
243 }
240 244
241 return color; 245 return color;
242 } 246 }
@@ -278,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
278 public void TerrainToBitmap(Bitmap mapbmp) 282 public void TerrainToBitmap(Bitmap mapbmp)
279 { 283 {
280 int tc = Environment.TickCount; 284 int tc = Environment.TickCount;
281 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 285 m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
282 286
283 // These textures should be in the AssetCache anyway, as every client conneting to this 287 // These textures should be in the AssetCache anyway, as every client conneting to this
284 // region needs them. Except on start, when the map is recreated (before anyone connected), 288 // region needs them. Except on start, when the map is recreated (before anyone connected),
@@ -412,7 +416,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
412 } 416 }
413 } 417 }
414 } 418 }
415 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 419
420 m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
416 } 421 }
417 } 422 }
418} 423} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 28daf2f..d4e4c25 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -205,13 +205,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
205 item.InvType = (int)InventoryType.Object; 205 item.InvType = (int)InventoryType.Object;
206 item.Folder = categoryID; 206 item.Folder = categoryID;
207 207
208 uint nextPerms=(perms & 7) << 13; 208 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
209 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
210 perms &= ~(uint)PermissionMask.Copy;
211 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
212 perms &= ~(uint)PermissionMask.Transfer;
213 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
214 perms &= ~(uint)PermissionMask.Modify;
215 209
216 item.BasePermissions = perms & part.NextOwnerMask; 210 item.BasePermissions = perms & part.NextOwnerMask;
217 item.CurrentPermissions = perms & part.NextOwnerMask; 211 item.CurrentPermissions = perms & part.NextOwnerMask;
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e434b2e..e77f0aa 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
546 { 546 {
547 ConsoleDisplayList cdl = new ConsoleDisplayList(); 547 ConsoleDisplayList cdl = new ConsoleDisplayList();
548 cdl.AddRow("Name", so.Name); 548 cdl.AddRow("Name", so.Name);
549 cdl.AddRow("Descrition", so.Description); 549 cdl.AddRow("Description", so.Description);
550 cdl.AddRow("Local ID", so.LocalId); 550 cdl.AddRow("Local ID", so.LocalId);
551 cdl.AddRow("UUID", so.UUID); 551 cdl.AddRow("UUID", so.UUID);
552 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); 552 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
@@ -631,7 +631,22 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
631 cdl.AddRow("SculptType", s.SculptType); 631 cdl.AddRow("SculptType", s.SculptType);
632 cdl.AddRow("State", s.State); 632 cdl.AddRow("State", s.State);
633 633
634 // TODO, unpack and display texture entries 634 // TODO, need to display more information about textures but in a compact format
635 // to stop output becoming huge.
636 for (int i = 0; i < sop.GetNumberOfSides(); i++)
637 {
638 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i];
639
640 UUID textureID;
641
642 if (teFace != null)
643 textureID = teFace.TextureID;
644 else
645 textureID = s.Textures.DefaultTexture.TextureID;
646
647 cdl.AddRow(string.Format("Face {0} texture ID", i), textureID);
648 }
649
635 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures. 650 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures.
636 } 651 }
637 652
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 4f5b9b7..616fe98 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1453,6 +1453,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1453 1453
1454 bool permission = false; 1454 bool permission = false;
1455 1455
1456// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
1457
1456 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 1458 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1457 if (land == null) return false; 1459 if (land == null) return false;
1458 1460
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 9c441ed..0c74b49 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -48,8 +48,8 @@ namespace OpenSim.Region.CoreModules.World.Region
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")]
49 public class RestartModule : INonSharedRegionModule, IRestartModule 49 public class RestartModule : INonSharedRegionModule, IRestartModule
50 { 50 {
51// private static readonly ILog m_log = 51 private static readonly ILog m_log =
52// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 protected Scene m_Scene; 54 protected Scene m_Scene;
55 protected Timer m_CountdownTimer = null; 55 protected Timer m_CountdownTimer = null;
@@ -223,11 +223,25 @@ namespace OpenSim.Region.CoreModules.World.Region
223 223
224 public void SetTimer(int intervalSeconds) 224 public void SetTimer(int intervalSeconds)
225 { 225 {
226 m_CountdownTimer = new Timer(); 226 if (intervalSeconds > 0)
227 m_CountdownTimer.AutoReset = false; 227 {
228 m_CountdownTimer.Interval = intervalSeconds * 1000; 228 m_CountdownTimer = new Timer();
229 m_CountdownTimer.Elapsed += OnTimer; 229 m_CountdownTimer.AutoReset = false;
230 m_CountdownTimer.Start(); 230 m_CountdownTimer.Interval = intervalSeconds * 1000;
231 m_CountdownTimer.Elapsed += OnTimer;
232 m_CountdownTimer.Start();
233 }
234 else if (m_CountdownTimer != null)
235 {
236 m_CountdownTimer.Stop();
237 m_CountdownTimer = null;
238 }
239 else
240 {
241 m_log.WarnFormat(
242 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
243 intervalSeconds, m_Scene.Name);
244 }
231 } 245 }
232 246
233 private void OnTimer(object source, ElapsedEventArgs e) 247 private void OnTimer(object source, ElapsedEventArgs e)
@@ -332,4 +346,4 @@ namespace OpenSim.Region.CoreModules.World.Region
332 } 346 }
333 } 347 }
334 } 348 }
335} \ No newline at end of file 349}
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index b4348c9..66059fb 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -144,7 +144,20 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
144 <Flags>None</Flags> 144 <Flags>None</Flags>
145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound> 145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound>
146 <CollisionSoundVolume>0</CollisionSoundVolume> 146 <CollisionSoundVolume>0</CollisionSoundVolume>
147 <DynAttrs><llsd><map><key>MyStore</key><map><key>the answer</key><integer>42</integer></map></map></llsd></DynAttrs> 147 <DynAttrs>
148 <llsd>
149 <map>
150 <key>MyNamespace</key>
151 <map>
152 <key>MyStore</key>
153 <map>
154 <key>the answer</key>
155 <integer>42</integer>
156 </map>
157 </map>
158 </map>
159 </llsd>
160 </DynAttrs>
148 </SceneObjectPart> 161 </SceneObjectPart>
149 </RootPart> 162 </RootPart>
150 <OtherParts /> 163 <OtherParts />
@@ -333,7 +346,20 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
333 <EveryoneMask>0</EveryoneMask> 346 <EveryoneMask>0</EveryoneMask>
334 <NextOwnerMask>2147483647</NextOwnerMask> 347 <NextOwnerMask>2147483647</NextOwnerMask>
335 <Flags>None</Flags> 348 <Flags>None</Flags>
336 <DynAttrs><llsd><map><key>MyStore</key><map><key>last words</key><string>Rosebud</string></map></map></llsd></DynAttrs> 349 <DynAttrs>
350 <llsd>
351 <map>
352 <key>MyNamespace</key>
353 <map>
354 <key>MyStore</key>
355 <map>
356 <key>last words</key>
357 <string>Rosebud</string>
358 </map>
359 </map>
360 </map>
361 </llsd>
362 </DynAttrs>
337 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar> 363 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar>
338 </SceneObjectPart> 364 </SceneObjectPart>
339 <OtherParts /> 365 <OtherParts />
@@ -362,7 +388,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
362 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); 388 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790")));
363 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); 389 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d")));
364 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); 390 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide"));
365 OSDMap store = rootPart.DynAttrs["MyStore"]; 391 OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore");
366 Assert.AreEqual(42, store["the answer"].AsInteger()); 392 Assert.AreEqual(42, store["the answer"].AsInteger());
367 393
368 // TODO: Check other properties 394 // TODO: Check other properties
@@ -414,13 +440,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
414 rp.CreatorID = rpCreatorId; 440 rp.CreatorID = rpCreatorId;
415 rp.Shape = shape; 441 rp.Shape = shape;
416 442
443 string daNamespace = "MyNamespace";
417 string daStoreName = "MyStore"; 444 string daStoreName = "MyStore";
418 string daKey = "foo"; 445 string daKey = "foo";
419 string daValue = "bar"; 446 string daValue = "bar";
420 OSDMap myStore = new OSDMap(); 447 OSDMap myStore = new OSDMap();
421 myStore.Add(daKey, daValue); 448 myStore.Add(daKey, daValue);
422 rp.DynAttrs = new DAMap(); 449 rp.DynAttrs = new DAMap();
423 rp.DynAttrs[daStoreName] = myStore; 450 rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore);
424 451
425 SceneObjectGroup so = new SceneObjectGroup(rp); 452 SceneObjectGroup so = new SceneObjectGroup(rp);
426 453
@@ -481,7 +508,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
481 Assert.That(name, Is.EqualTo(rpName)); 508 Assert.That(name, Is.EqualTo(rpName));
482 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 509 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
483 Assert.NotNull(daMap); 510 Assert.NotNull(daMap);
484 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); 511 Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString());
485 } 512 }
486 513
487 [Test] 514 [Test]
@@ -496,7 +523,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
496 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); 523 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946")));
497 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); 524 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef")));
498 Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); 525 Assert.That(rootPart.Name, Is.EqualTo("PrimFun"));
499 OSDMap store = rootPart.DynAttrs["MyStore"]; 526 OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore");
500 Assert.AreEqual("Rosebud", store["last words"].AsString()); 527 Assert.AreEqual("Rosebud", store["last words"].AsString());
501 528
502 // TODO: Check other properties 529 // TODO: Check other properties
@@ -522,13 +549,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
522 rp.CreatorID = rpCreatorId; 549 rp.CreatorID = rpCreatorId;
523 rp.Shape = shape; 550 rp.Shape = shape;
524 551
552 string daNamespace = "MyNamespace";
525 string daStoreName = "MyStore"; 553 string daStoreName = "MyStore";
526 string daKey = "foo"; 554 string daKey = "foo";
527 string daValue = "bar"; 555 string daValue = "bar";
528 OSDMap myStore = new OSDMap(); 556 OSDMap myStore = new OSDMap();
529 myStore.Add(daKey, daValue); 557 myStore.Add(daKey, daValue);
530 rp.DynAttrs = new DAMap(); 558 rp.DynAttrs = new DAMap();
531 rp.DynAttrs[daStoreName] = myStore; 559 rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore);
532 560
533 SceneObjectGroup so = new SceneObjectGroup(rp); 561 SceneObjectGroup so = new SceneObjectGroup(rp);
534 562
@@ -585,7 +613,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
585 Assert.That(name, Is.EqualTo(rpName)); 613 Assert.That(name, Is.EqualTo(rpName));
586 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 614 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
587 Assert.NotNull(daMap); 615 Assert.NotNull(daMap);
588 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); 616 Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString());
589 } 617 }
590 } 618 }
591} \ No newline at end of file 619} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 883045a..9c99c19 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -48,6 +48,18 @@ namespace OpenSim.Region.CoreModules.World.Sound
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
51 public enum SoundFlags: byte
52 {
53 NONE = 0,
54 LOOP = 1 << 0,
55 SYNC_MASTER = 1<<1,
56 SYNC_SLAVE = 1<<2,
57 SYNC_PENDING = 1<<3,
58 QUEUE = 1<<4,
59 STOP = 1<<5,
60 SYNC_MASK = SYNC_MASTER | SYNC_SLAVE | SYNC_PENDING
61 }
62
51 public bool Enabled { get; private set; } 63 public bool Enabled { get; private set; }
52 64
53 public float MaxDistance { get; private set; } 65 public float MaxDistance { get; private set; }
@@ -124,26 +136,30 @@ namespace OpenSim.Region.CoreModules.World.Sound
124 if (radius == 0) 136 if (radius == 0)
125 radius = MaxDistance; 137 radius = MaxDistance;
126 138
127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 139 if (part.SoundQueueing)
140 flags |= (byte)SoundFlags.QUEUE;
141
142 if (grp.IsAttachment)
128 { 143 {
129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 144 ScenePresence ssp = null;
130 if (dis > MaxDistance) // Max audio distance 145 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
131 return; 146 return;
132 147
133 if (grp.IsAttachment) 148 if (!ssp.ParcelAllowThisAvatarSounds)
134 { 149 return;
135 if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID)
136 return;
137 150
138 if (sp.ControllingClient.AgentId == grp.OwnerID) 151 if (grp.HasPrivateAttachmentPoint)
139 dis = 0; 152 {
153 ssp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
154 ownerID, (float)gain, flags);
155 return;
140 } 156 }
157 }
141 158
142 // Scale by distance 159 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
143 double thisSpGain = gain * ((radius - dis) / radius); 160 {
144
145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, 161 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags); 162 ownerID, (float)gain, flags);
147 }); 163 });
148 } 164 }
149 165
@@ -151,20 +167,33 @@ namespace OpenSim.Region.CoreModules.World.Sound
151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 167 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
152 { 168 {
153 SceneObjectPart part; 169 SceneObjectPart part;
170 ScenePresence ssp = null;
154 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 171 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
155 { 172 {
156 ScenePresence sp; 173 if (!m_scene.TryGetScenePresence(ownerID, out ssp))
157 if (!m_scene.TryGetScenePresence(ownerID, out sp)) 174 return;
175 if (!ssp.ParcelAllowThisAvatarSounds)
158 return; 176 return;
159 } 177 }
160 else 178 else
161 { 179 {
162 SceneObjectGroup grp = part.ParentGroup; 180 SceneObjectGroup grp = part.ParentGroup;
163 181
164 if (grp.IsAttachment && grp.AttachmentPoint > 30) 182 if (grp.IsAttachment)
165 { 183 {
166 objectID = ownerID; 184 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
167 parentID = ownerID; 185 return;
186
187 if (!ssp.ParcelAllowThisAvatarSounds)
188 return;
189
190 if (grp.HasPrivateAttachmentPoint)
191 {
192 ssp.ControllingClient.SendTriggeredSound(soundId, ownerID,
193 objectID, parentID, handle, position,
194 (float)gain);
195 return;
196 }
168 } 197 }
169 } 198 }
170 199
@@ -174,16 +203,12 @@ namespace OpenSim.Region.CoreModules.World.Sound
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 203 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 204 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 205 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 206 if (dis > radius) // Max audio distance
178 if (dis > MaxDistance) // Max audio distance
179 return; 207 return;
180 208
181 // Scale by distance
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID, 209 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position, 210 objectID, parentID, handle, position,
186 (float)thisSpGain); 211 (float)gain);
187 }); 212 });
188 } 213 }
189 214
@@ -198,40 +223,13 @@ namespace OpenSim.Region.CoreModules.World.Sound
198 223
199 private static void StopSound(SceneObjectPart m_host) 224 private static void StopSound(SceneObjectPart m_host)
200 { 225 {
201 m_host.AdjustSoundGain(0); 226// m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead 227 m_host.Sound = UUID.Zero;
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 228 m_host.SoundFlags = (byte)SoundFlags.STOP;
204 { 229 m_host.SoundRadius = 0;
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 230 m_host.SoundGain = 0;
206 { 231 m_host.ScheduleFullUpdate();
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) 232 m_host.SendFullUpdateToAllClients();
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 } 233 }
236 234
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) 235 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
@@ -248,7 +246,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
248 246
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 247 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 { 248 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) 249 if (Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) < radius)
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); 250 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 }); 251 });
254 } 252 }
@@ -262,21 +260,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
262 // 20080530 Updated to remove code duplication 260 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work 261 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID, 262 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster) 263 double volume, double radius, bool isMaster, bool isSlave)
266 { 264 {
267 SceneObjectPart m_host; 265 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) 266 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return; 267 return;
270 268
269 byte iflags = 1; // looping
271 if (isMaster) 270 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 271 iflags |= (byte)SoundFlags.SYNC_MASTER;
273 272 // TODO check viewer seems to accept both
274 if (m_host.Sound != UUID.Zero) 273 if (isSlave)
275 StopSound(m_host); 274 iflags |= (byte)SoundFlags.SYNC_SLAVE;
275 if (m_host.SoundQueueing)
276 iflags |= (byte)SoundFlags.QUEUE;
276 277
277 m_host.Sound = soundID; 278 m_host.Sound = soundID;
278 m_host.SoundGain = volume; 279 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping 280 m_host.SoundFlags = iflags;
280 m_host.SoundRadius = radius; 281 m_host.SoundRadius = radius;
281 282
282 m_host.ScheduleFullUpdate(); 283 m_host.ScheduleFullUpdate();
@@ -301,42 +302,19 @@ namespace OpenSim.Region.CoreModules.World.Sound
301 Vector3 position = part.AbsolutePosition; // region local 302 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle; 303 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303 304
304 if (useMaster) 305 if(triggered)
305 { 306 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else 307 else
334 { 308 {
335 if (triggered) 309 byte bflags = 0;
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); 310
337 else 311 if (isMaster)
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); 312 bflags |= (byte)SoundFlags.SYNC_MASTER;
339 } 313 // TODO check viewer seems to accept both
314 if (useMaster)
315 bflags |= (byte)SoundFlags.SYNC_SLAVE;
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, bflags, radius);
317 }
340 } 318 }
341 319
342 public void TriggerSoundLimited(UUID objectID, UUID sound, 320 public void TriggerSoundLimited(UUID objectID, UUID sound,
@@ -369,6 +347,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
369 }); 347 });
370 } 348 }
371 349
350 public void SetSoundQueueing(UUID objectID, bool shouldQueue)
351 {
352 SceneObjectPart part;
353 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
354 return;
355
356 part.SoundQueueing = shouldQueue;
357 }
358
372 #endregion 359 #endregion
373 } 360 }
374} 361}
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 9de588c..35014f5 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -216,13 +216,13 @@ namespace OpenSim.Region.CoreModules
216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no 216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no
217 // way to prevent this, short of making the entire module shared (which is complete overkill). 217 // way to prevent this, short of making the entire module shared (which is complete overkill).
218 // One possibility is to return a bool to signal whether the module has completely handled the command 218 // One possibility is to return a bool to signal whether the module has completely handled the command
219 m_log.InfoFormat("[WIND]: Please change to a specific region in order to set Sun parameters."); 219 MainConsole.Instance.Output("Please change to a specific region in order to set Sun parameters.");
220 return; 220 return;
221 } 221 }
222 222
223 if (m_scene.ConsoleScene() != m_scene) 223 if (m_scene.ConsoleScene() != m_scene)
224 { 224 {
225 m_log.InfoFormat("[WIND]: Console Scene is not my scene."); 225 MainConsole.Instance.Output("Console Scene is not my scene.");
226 return; 226 return;
227 } 227 }
228 } 228 }
@@ -233,7 +233,9 @@ namespace OpenSim.Region.CoreModules
233 private void HandleConsoleCommand(string module, string[] cmdparams) 233 private void HandleConsoleCommand(string module, string[] cmdparams)
234 { 234 {
235 ValidateConsole(); 235 ValidateConsole();
236 m_log.Info("[WIND] The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins."); 236
237 MainConsole.Instance.Output(
238 "The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins.");
237 } 239 }
238 240
239 /// <summary> 241 /// <summary>
@@ -246,7 +248,9 @@ namespace OpenSim.Region.CoreModules
246 if ((cmdparams.Length != 4) 248 if ((cmdparams.Length != 4)
247 || !cmdparams[1].Equals("base")) 249 || !cmdparams[1].Equals("base"))
248 { 250 {
249 m_log.Info("[WIND] Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>"); 251 MainConsole.Instance.Output(
252 "Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>");
253
250 return; 254 return;
251 } 255 }
252 256
@@ -261,7 +265,9 @@ namespace OpenSim.Region.CoreModules
261 } 265 }
262 else 266 else
263 { 267 {
264 m_log.InfoFormat("[WIND] Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]); 268 MainConsole.Instance.OutputFormat(
269 "Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]);
270
265 return; 271 return;
266 } 272 }
267 273
@@ -271,22 +277,23 @@ namespace OpenSim.Region.CoreModules
271 277
272 if (desiredPlugin.Equals(m_activeWindPlugin.Name)) 278 if (desiredPlugin.Equals(m_activeWindPlugin.Name))
273 { 279 {
274 m_log.InfoFormat("[WIND] Wind model plugin {0} is already active", cmdparams[3]); 280 MainConsole.Instance.OutputFormat("Wind model plugin {0} is already active", cmdparams[3]);
281
275 return; 282 return;
276 } 283 }
277 284
278 if (m_availableWindPlugins.ContainsKey(desiredPlugin)) 285 if (m_availableWindPlugins.ContainsKey(desiredPlugin))
279 { 286 {
280 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]]; 287 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]];
281 m_log.InfoFormat("[WIND] {0} wind model plugin now active", m_activeWindPlugin.Name); 288
289 MainConsole.Instance.OutputFormat("{0} wind model plugin now active", m_activeWindPlugin.Name);
282 } 290 }
283 else 291 else
284 { 292 {
285 m_log.InfoFormat("[WIND] Could not find wind model plugin {0}", desiredPlugin); 293 MainConsole.Instance.OutputFormat("Could not find wind model plugin {0}", desiredPlugin);
286 } 294 }
287 break; 295 break;
288 } 296 }
289
290 } 297 }
291 298
292 /// <summary> 299 /// <summary>
@@ -300,7 +307,7 @@ namespace OpenSim.Region.CoreModules
300 if ((cmdparams.Length != 4) 307 if ((cmdparams.Length != 4)
301 && (cmdparams.Length != 3)) 308 && (cmdparams.Length != 3))
302 { 309 {
303 m_log.Info("[WIND] Usage: wind <plugin> <param> [value]"); 310 MainConsole.Instance.Output("Usage: wind <plugin> <param> [value]");
304 return; 311 return;
305 } 312 }
306 313
@@ -311,16 +318,17 @@ namespace OpenSim.Region.CoreModules
311 { 318 {
312 if (!float.TryParse(cmdparams[3], out value)) 319 if (!float.TryParse(cmdparams[3], out value))
313 { 320 {
314 m_log.InfoFormat("[WIND] Invalid value {0}", cmdparams[3]); 321 MainConsole.Instance.OutputFormat("Invalid value {0}", cmdparams[3]);
315 } 322 }
316 323
317 try 324 try
318 { 325 {
319 WindParamSet(plugin, param, value); 326 WindParamSet(plugin, param, value);
327 MainConsole.Instance.OutputFormat("{0} set to {1}", param, value);
320 } 328 }
321 catch (Exception e) 329 catch (Exception e)
322 { 330 {
323 m_log.InfoFormat("[WIND] {0}", e.Message); 331 MainConsole.Instance.OutputFormat("{0}", e.Message);
324 } 332 }
325 } 333 }
326 else 334 else
@@ -328,11 +336,11 @@ namespace OpenSim.Region.CoreModules
328 try 336 try
329 { 337 {
330 value = WindParamGet(plugin, param); 338 value = WindParamGet(plugin, param);
331 m_log.InfoFormat("[WIND] {0} : {1}", param, value); 339 MainConsole.Instance.OutputFormat("{0} : {1}", param, value);
332 } 340 }
333 catch (Exception e) 341 catch (Exception e)
334 { 342 {
335 m_log.InfoFormat("[WIND] {0}", e.Message); 343 MainConsole.Instance.OutputFormat("{0}", e.Message);
336 } 344 }
337 } 345 }
338 346
@@ -366,13 +374,11 @@ namespace OpenSim.Region.CoreModules
366 { 374 {
367 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin]; 375 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
368 windPlugin.WindParamSet(param, value); 376 windPlugin.WindParamSet(param, value);
369 m_log.InfoFormat("[WIND] {0} set to {1}", param, value);
370 } 377 }
371 else 378 else
372 { 379 {
373 throw new Exception(String.Format("Could not find plugin {0}", plugin)); 380 throw new Exception(String.Format("Could not find plugin {0}", plugin));
374 } 381 }
375
376 } 382 }
377 383
378 public float WindParamGet(string plugin, string param) 384 public float WindParamGet(string plugin, string param)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index bf18616..5412359 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
115 "export-map [<path>]", 115 "export-map [<path>]",
116 "Save an image of the world map", HandleExportWorldMapConsoleCommand); 116 "Save an image of the world map", HandleExportWorldMapConsoleCommand);
117 117
118 m_scene.AddCommand(
119 "Regions", this, "generate map",
120 "generate map",
121 "Generates and stores a new maptile.", HandleGenerateMapConsoleCommand);
122
118 AddHandlers(); 123 AddHandlers();
119 } 124 }
120 } 125 }
@@ -162,7 +167,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
162 regionimage = regionimage.Replace("-", ""); 167 regionimage = regionimage.Replace("-", "");
163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 168 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
164 169
165 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); 170 MainServer.Instance.AddHTTPHandler(regionimage,
171 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
172 {
173 AllowXForwardedFor = false,
174 ForgetTimeSpan = TimeSpan.FromMinutes(2),
175 MaxRequestsInTimeframe = 4,
176 ReportingName = "MAPDOSPROTECTOR",
177 RequestTimeSpan = TimeSpan.FromSeconds(10),
178 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
179 }).Process);
166 MainServer.Instance.AddLLSDHandler( 180 MainServer.Instance.AddLLSDHandler(
167 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 181 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
168 182
@@ -1131,6 +1145,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1131 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); 1145 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1132 } 1146 }
1133 1147
1148 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1149 {
1150 Hashtable reply = new Hashtable();
1151 int statuscode = 500;
1152 reply["str_response_string"] = "";
1153 reply["int_response_code"] = statuscode;
1154 reply["content_type"] = "text/plain";
1155 return reply;
1156 }
1157
1134 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1158 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1135 { 1159 {
1136 m_log.Debug("[WORLD MAP]: Sending map image jpeg"); 1160 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
@@ -1305,6 +1329,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1305 m_scene.RegionInfo.RegionName, exportPath); 1329 m_scene.RegionInfo.RegionName, exportPath);
1306 } 1330 }
1307 1331
1332 public void HandleGenerateMapConsoleCommand(string module, string[] cmdparams)
1333 {
1334 Scene consoleScene = m_scene.ConsoleScene();
1335
1336 if (consoleScene != null && consoleScene != m_scene)
1337 return;
1338
1339 GenerateMaptile();
1340 }
1341
1308 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1342 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
1309 { 1343 {
1310 uint xstart = 0; 1344 uint xstart = 0;
@@ -1542,88 +1576,69 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1542 1576
1543 private Byte[] GenerateOverlay() 1577 private Byte[] GenerateOverlay()
1544 { 1578 {
1545 Bitmap overlay = new Bitmap(256, 256); 1579 using (Bitmap overlay = new Bitmap(256, 256))
1546
1547 bool[,] saleBitmap = new bool[64, 64];
1548 for (int x = 0 ; x < 64 ; x++)
1549 { 1580 {
1550 for (int y = 0 ; y < 64 ; y++) 1581 bool[,] saleBitmap = new bool[64, 64];
1551 saleBitmap[x, y] = false; 1582 for (int x = 0 ; x < 64 ; x++)
1552 } 1583 {
1553 1584 for (int y = 0 ; y < 64 ; y++)
1554 bool landForSale = false; 1585 saleBitmap[x, y] = false;
1586 }
1555 1587
1556 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1588 bool landForSale = false;
1557 1589
1558 Color background = Color.FromArgb(0, 0, 0, 0); 1590 List<ILandObject> parcels = m_scene.LandChannel.AllParcels();
1559 SolidBrush transparent = new SolidBrush(background);
1560 Graphics g = Graphics.FromImage(overlay);
1561 g.FillRectangle(transparent, 0, 0, 255, 255);
1562 1591
1563 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1592 Color background = Color.FromArgb(0, 0, 0, 0);
1564 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1565 1593
1566 foreach (ILandObject land in parcels) 1594 using (Graphics g = Graphics.FromImage(overlay))
1567 {
1568 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1569 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1570 { 1595 {
1571 landForSale = true; 1596 using (SolidBrush transparent = new SolidBrush(background))
1572 1597 g.FillRectangle(transparent, 0, 0, 256, 256);
1573 bool[,] landBitmap = land.GetLandBitmap();
1574 1598
1575 for (int x = 0 ; x < 64 ; x++) 1599
1600 foreach (ILandObject land in parcels)
1576 { 1601 {
1577 for (int y = 0 ; y < 64 ; y++) 1602 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1603 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1578 { 1604 {
1579 if (landBitmap[x, y]) 1605 landForSale = true;
1606
1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1608 }
1609 }
1610
1611 if (!landForSale)
1612 {
1613 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1614 return null;
1615 }
1616
1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1618
1619 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
1620 {
1621 for (int x = 0 ; x < 64 ; x++)
1622 {
1623 for (int y = 0 ; y < 64 ; y++)
1580 { 1624 {
1581 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4); 1625 if (saleBitmap[x, y])
1582 1626 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1583 if (x > 0)
1584 {
1585 if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
1586 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
1587 }
1588 if (y > 0)
1589 {
1590 if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
1591 g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
1592 }
1593 if (x < 63)
1594 {
1595 if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
1596 g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
1597 }
1598 if (y < 63)
1599 {
1600 if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
1601 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
1602 }
1603 } 1627 }
1604 } 1628 }
1605 } 1629 }
1606
1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1608 } 1630 }
1609 }
1610 1631
1611 if (!landForSale) 1632 try
1612 { 1633 {
1613 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); 1634 return OpenJPEG.EncodeFromImage(overlay, true);
1614 return null; 1635 }
1636 catch (Exception e)
1637 {
1638 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
1639 }
1615 } 1640 }
1616 1641
1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1618
1619 try
1620 {
1621 return OpenJPEG.EncodeFromImage(overlay, true);
1622 }
1623 catch (Exception e)
1624 {
1625 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
1626 }
1627 return null; 1642 return null;
1628 } 1643 }
1629 } 1644 }