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.cs6
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs186
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs6
-rw-r--r--OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs4
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs169
-rw-r--r--OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs120
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs556
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs208
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs260
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs100
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs168
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs57
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs421
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs14
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs228
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs229
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs454
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs85
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs12
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs20
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs14
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs359
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs76
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs115
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs148
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs624
54 files changed, 3182 insertions, 1782 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 0271738..da1ff2e 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
143 } 143 }
144 } 144 }
145 145
146 public void RequestCreateInventoryItem(IClientAPI remoteClient, 146 public bool RequestCreateInventoryItem(IClientAPI remoteClient,
147 UUID transactionID, UUID folderID, uint callbackID, 147 UUID transactionID, UUID folderID, uint callbackID,
148 string description, string name, sbyte invType, 148 string description, string name, sbyte invType,
149 sbyte type, byte wearableType, uint nextOwnerMask) 149 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -153,6 +153,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
153 uploader.RequestCreateInventoryItem( 153 uploader.RequestCreateInventoryItem(
154 remoteClient, folderID, callbackID, 154 remoteClient, folderID, callbackID,
155 description, name, invType, type, wearableType, nextOwnerMask); 155 description, name, invType, type, wearableType, nextOwnerMask);
156
157 return true;
156 } 158 }
157 159
158 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 160 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
@@ -172,4 +174,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
172 uploader.RequestUpdateInventoryItem(remoteClient, item); 174 uploader.RequestUpdateInventoryItem(remoteClient, item);
173 } 175 }
174 } 176 }
175} \ No newline at end of file 177}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index b67c0df..f489262 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
158 /// <param name="type"></param> 158 /// <param name="type"></param>
159 /// <param name="wearableType"></param> 159 /// <param name="wearableType"></param>
160 /// <param name="nextOwnerMask"></param> 160 /// <param name="nextOwnerMask"></param>
161 public void HandleItemCreationFromTransaction(IClientAPI remoteClient, 161 public bool HandleItemCreationFromTransaction(IClientAPI remoteClient,
162 UUID transactionID, UUID folderID, uint callbackID, 162 UUID transactionID, UUID folderID, uint callbackID,
163 string description, string name, sbyte invType, 163 string description, string name, sbyte invType,
164 sbyte type, byte wearableType, uint nextOwnerMask) 164 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
169 AgentAssetTransactions transactions = 169 AgentAssetTransactions transactions =
170 GetUserTransactions(remoteClient.AgentId); 170 GetUserTransactions(remoteClient.AgentId);
171 171
172 transactions.RequestCreateInventoryItem(remoteClient, transactionID, 172 return transactions.RequestCreateInventoryItem(remoteClient, transactionID,
173 folderID, callbackID, description, name, invType, type, 173 folderID, callbackID, description, name, invType, type,
174 wearableType, nextOwnerMask); 174 wearableType, nextOwnerMask);
175 } 175 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 5e772e6..ffff37d 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Collections.Generic;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -39,6 +40,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
39{ 40{
40 public class AssetXferUploader 41 public class AssetXferUploader
41 { 42 {
43 // Viewer's notion of the default texture
44 private List<UUID> defaultIDs = new List<UUID> {
45 new UUID("5748decc-f629-461c-9a36-a35a221fe21f"),
46 new UUID("7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"),
47 new UUID("6522e74d-1660-4e7f-b601-6f48c1659a77"),
48 new UUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97")
49 };
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 51
44 /// <summary> 52 /// <summary>
@@ -86,6 +94,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
86 94
87 private sbyte type = 0; 95 private sbyte type = 0;
88 private byte wearableType = 0; 96 private byte wearableType = 0;
97 private byte[] m_oldData = null;
89 public ulong XferID; 98 public ulong XferID;
90 private Scene m_Scene; 99 private Scene m_Scene;
91 100
@@ -128,18 +137,27 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
128 137
129 if (XferID == xferID) 138 if (XferID == xferID)
130 { 139 {
131 if (m_asset.Data.Length > 1) 140 lock (this)
132 { 141 {
133 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; 142 int assetLength = m_asset.Data.Length;
134 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); 143 int dataLength = data.Length;
135 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); 144
136 m_asset.Data = destinationArray; 145 if (m_asset.Data.Length > 1)
137 } 146 {
138 else 147 byte[] destinationArray = new byte[assetLength + dataLength];
139 { 148 Array.Copy(m_asset.Data, 0, destinationArray, 0, assetLength);
140 byte[] buffer2 = new byte[data.Length - 4]; 149 Array.Copy(data, 0, destinationArray, assetLength, dataLength);
141 Array.Copy(data, 4, buffer2, 0, data.Length - 4); 150 m_asset.Data = destinationArray;
142 m_asset.Data = buffer2; 151 }
152 else
153 {
154 if (dataLength > 4)
155 {
156 byte[] buffer2 = new byte[dataLength - 4];
157 Array.Copy(data, 4, buffer2, 0, dataLength - 4);
158 m_asset.Data = buffer2;
159 }
160 }
143 } 161 }
144 162
145 ourClient.SendConfirmXfer(xferID, packetID); 163 ourClient.SendConfirmXfer(xferID, packetID);
@@ -243,10 +261,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
243 { 261 {
244 CompleteTaskItemUpdate(m_updateTaskItemData); 262 CompleteTaskItemUpdate(m_updateTaskItemData);
245 } 263 }
246// else if (m_storeLocal) 264 else if (m_asset.Local)
247// { 265 {
248// m_Scene.AssetService.Store(m_asset); 266 m_Scene.AssetService.Store(m_asset);
249// } 267 }
250 } 268 }
251 269
252 m_log.DebugFormat( 270 m_log.DebugFormat(
@@ -374,6 +392,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
374// m_asset.FullID, item.Name, ourClient.Name); 392// m_asset.FullID, item.Name, ourClient.Name);
375 393
376 m_Scene.AssetService.Store(m_asset); 394 m_Scene.AssetService.Store(m_asset);
395 if (m_asset.FullID != UUID.Zero)
396 {
397 item.AssetID = m_asset.FullID;
398 m_Scene.InventoryService.UpdateItem(item);
399 }
377 400
378 m_transactions.RemoveXferUploader(m_transactionID); 401 m_transactions.RemoveXferUploader(m_transactionID);
379 } 402 }
@@ -395,6 +418,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
395 418
396 private void CompleteCreateItem(uint callbackID) 419 private void CompleteCreateItem(uint callbackID)
397 { 420 {
421 ValidateAssets();
398 m_Scene.AssetService.Store(m_asset); 422 m_Scene.AssetService.Store(m_asset);
399 423
400 InventoryItemBase item = new InventoryItemBase(); 424 InventoryItemBase item = new InventoryItemBase();
@@ -415,6 +439,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
415 item.Flags = (uint) wearableType; 439 item.Flags = (uint) wearableType;
416 item.CreationDate = Util.UnixTimeSinceEpoch(); 440 item.CreationDate = Util.UnixTimeSinceEpoch();
417 441
442 m_log.DebugFormat("[XFER]: Created item {0} with asset {1}",
443 item.ID, item.AssetID);
444
418 if (m_Scene.AddInventoryItem(item)) 445 if (m_Scene.AddInventoryItem(item))
419 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 446 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
420 else 447 else
@@ -422,5 +449,132 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
422 449
423 m_transactions.RemoveXferUploader(m_transactionID); 450 m_transactions.RemoveXferUploader(m_transactionID);
424 } 451 }
452
453 private void ValidateAssets()
454 {
455 if (m_asset.Type == (sbyte)AssetType.Clothing ||
456 m_asset.Type == (sbyte)AssetType.Bodypart)
457 {
458 string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
459 string[] lines = content.Split(new char[] {'\n'});
460
461 List<string> validated = new List<string>();
462
463 Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
464
465 int textures = 0;
466
467 foreach (string line in lines)
468 {
469 try
470 {
471 if (line.StartsWith("textures "))
472 {
473 textures = Convert.ToInt32(line.Substring(9));
474 validated.Add(line);
475 }
476 else if (textures > 0)
477 {
478 string[] parts = line.Split(new char[] {' '});
479
480 UUID tx = new UUID(parts[1]);
481 int id = Convert.ToInt32(parts[0]);
482
483 if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
484 (allowed.ContainsKey(id) && allowed[id] == tx))
485 {
486 validated.Add(parts[0] + " " + tx.ToString());
487 }
488 else
489 {
490 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
491 int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
492
493 if ((perms & full) != full)
494 {
495 m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
496 validated.Add(parts[0] + " " + UUID.Zero.ToString());
497 }
498 else
499 {
500 validated.Add(line);
501 }
502 }
503 textures--;
504 }
505 else
506 {
507 validated.Add(line);
508 }
509 }
510 catch
511 {
512 // If it's malformed, skip it
513 }
514 }
515
516 string final = String.Join("\n", validated.ToArray());
517
518 m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
519 }
520 }
521
522 /// <summary>
523 /// Get the asset data uploaded in this transfer.
524 /// </summary>
525 /// <returns>null if the asset has not finished uploading</returns>
526 public AssetBase GetAssetData()
527 {
528 if (m_uploadState == UploadState.Complete)
529 {
530 ValidateAssets();
531 return m_asset;
532 }
533
534 return null;
535 }
536
537 public void SetOldData(byte[] d)
538 {
539 m_oldData = d;
540 }
541
542 private Dictionary<int,UUID> ExtractTexturesFromOldData()
543 {
544 Dictionary<int,UUID> result = new Dictionary<int,UUID>();
545 if (m_oldData == null)
546 return result;
547
548 string content = System.Text.Encoding.ASCII.GetString(m_oldData);
549 string[] lines = content.Split(new char[] {'\n'});
550
551 int textures = 0;
552
553 foreach (string line in lines)
554 {
555 try
556 {
557 if (line.StartsWith("textures "))
558 {
559 textures = Convert.ToInt32(line.Substring(9));
560 }
561 else if (textures > 0)
562 {
563 string[] parts = line.Split(new char[] {' '});
564
565 UUID tx = new UUID(parts[1]);
566 int id = Convert.ToInt32(parts[0]);
567 result[id] = tx;
568 textures--;
569 }
570 }
571 catch
572 {
573 // If it's malformed, skip it
574 }
575 }
576
577 return result;
578 }
425 } 579 }
426} \ No newline at end of file 580}
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
index 4299726..7113f4f 100644
--- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
@@ -160,6 +160,8 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
160 { 160 {
161 byte[] fileData = NewFiles[fileName].Data; 161 byte[] fileData = NewFiles[fileName].Data;
162 XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); 162 XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
163 if (fileName.StartsWith("inventory_"))
164 transaction.isTaskInventory = true;
163 165
164 Transfers.Add(xferID, transaction); 166 Transfers.Add(xferID, transaction);
165 167
@@ -243,6 +245,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
243 public uint Packet = 0; 245 public uint Packet = 0;
244 public uint Serial = 1; 246 public uint Serial = 1;
245 public ulong XferID = 0; 247 public ulong XferID = 0;
248 public bool isTaskInventory = false;
246 249
247 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) 250 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
248 { 251 {
@@ -268,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
268 byte[] transferData = new byte[Data.Length + 4]; 271 byte[] transferData = new byte[Data.Length + 4];
269 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 272 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4);
270 Array.Copy(Data, 0, transferData, 4, Data.Length); 273 Array.Copy(Data, 0, transferData, 4, Data.Length);
271 Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); 274 Client.SendXferPacket(XferID, 0 + 0x80000000, transferData, isTaskInventory);
272 complete = true; 275 complete = true;
273 } 276 }
274 else 277 else
@@ -276,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
276 byte[] transferData = new byte[1000 + 4]; 279 byte[] transferData = new byte[1000 + 4];
277 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 280 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4);
278 Array.Copy(Data, 0, transferData, 4, 1000); 281 Array.Copy(Data, 0, transferData, 4, 1000);
279 Client.SendXferPacket(XferID, 0, transferData); 282 Client.SendXferPacket(XferID, 0, transferData, isTaskInventory);
280 Packet++; 283 Packet++;
281 DataPointer = 1000; 284 DataPointer = 1000;
282 } 285 }
@@ -297,7 +300,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
297 { 300 {
298 byte[] transferData = new byte[1000]; 301 byte[] transferData = new byte[1000];
299 Array.Copy(Data, DataPointer, transferData, 0, 1000); 302 Array.Copy(Data, DataPointer, transferData, 0, 1000);
300 Client.SendXferPacket(XferID, Packet, transferData); 303 Client.SendXferPacket(XferID, Packet, transferData, isTaskInventory);
301 Packet++; 304 Packet++;
302 DataPointer += 1000; 305 DataPointer += 1000;
303 } 306 }
@@ -306,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
306 byte[] transferData = new byte[Data.Length - DataPointer]; 309 byte[] transferData = new byte[Data.Length - DataPointer];
307 Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); 310 Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
308 uint endPacket = Packet |= (uint) 0x80000000; 311 uint endPacket = Packet |= (uint) 0x80000000;
309 Client.SendXferPacket(XferID, endPacket, transferData); 312 Client.SendXferPacket(XferID, endPacket, transferData, isTaskInventory);
310 Packet++; 313 Packet++;
311 DataPointer += (Data.Length - DataPointer); 314 DataPointer += (Data.Length - DataPointer);
312 315
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index e40caec..f43305f 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -194,6 +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)
199 {
200 return false;
201 }
202
197 /// <summary> 203 /// <summary>
198 /// Cache asset. 204 /// Cache asset.
199 /// </summary> 205 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index 9742a5c..58ce61a 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -112,6 +112,10 @@ namespace OpenSim.Region.CoreModules.Asset
112 //////////////////////////////////////////////////////////// 112 ////////////////////////////////////////////////////////////
113 // IImprovedAssetCache 113 // IImprovedAssetCache
114 // 114 //
115 public bool Check(string id)
116 {
117 return false;
118 }
115 119
116 public void Cache(AssetBase asset) 120 public void Cache(AssetBase asset)
117 { 121 {
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 2afe065..d510d82 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -251,57 +251,70 @@ namespace OpenSim.Region.CoreModules.Asset
251 251
252 private void UpdateFileCache(string key, AssetBase asset) 252 private void UpdateFileCache(string key, AssetBase asset)
253 { 253 {
254 string filename = GetFileName(asset.ID); 254 // TODO: Spawn this off to some seperate thread to do the actual writing
255 255 if (asset != null)
256 try
257 { 256 {
258 // If the file is already cached just update access time. 257 string filename = GetFileName(key);
259 if (File.Exists(filename)) 258
260 { 259 try
261 lock (m_CurrentlyWriting)
262 {
263 if (!m_CurrentlyWriting.Contains(filename))
264 File.SetLastAccessTime(filename, DateTime.Now);
265 }
266 }
267 else
268 { 260 {
269 // Once we start writing, make sure we flag that we're writing 261 // If the file is already cached, don't cache it, just touch it so access time is updated
270 // that object to the cache so that we don't try to write the 262 if (File.Exists(filename))
271 // same file multiple times.
272 lock (m_CurrentlyWriting)
273 { 263 {
274#if WAIT_ON_INPROGRESS_REQUESTS 264 // We don't really want to know about sharing
275 if (m_CurrentlyWriting.ContainsKey(filename)) 265 // violations here. If the file is locked, then
266 // the other thread has updated the time for us.
267 try
276 { 268 {
277 return; 269 lock (m_CurrentlyWriting)
270 {
271 if (!m_CurrentlyWriting.Contains(filename))
272 File.SetLastAccessTime(filename, DateTime.Now);
273 }
278 } 274 }
279 else 275 catch
280 {
281 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
282 }
283
284#else
285 if (m_CurrentlyWriting.Contains(filename))
286 { 276 {
287 return;
288 } 277 }
289 else 278 } 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)
290 { 284 {
291 m_CurrentlyWriting.Add(filename); 285#if WAIT_ON_INPROGRESS_REQUESTS
292 } 286 if (m_CurrentlyWriting.ContainsKey(filename))
287 {
288 return;
289 }
290 else
291 {
292 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
293 }
294
295#else
296 if (m_CurrentlyWriting.Contains(filename))
297 {
298 return;
299 }
300 else
301 {
302 m_CurrentlyWriting.Add(filename);
303 }
293#endif 304#endif
294 }
295 305
296 Util.FireAndForget( 306 }
297 delegate { WriteFileCache(filename, asset); }); 307
308 Util.FireAndForget(
309 delegate { WriteFileCache(filename, asset); });
310 }
311 }
312 catch (Exception e)
313 {
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);
298 } 317 }
299 }
300 catch (Exception e)
301 {
302 m_log.WarnFormat(
303 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
304 asset.ID, e.Message, e.StackTrace);
305 } 318 }
306 } 319 }
307 320
@@ -335,6 +348,17 @@ namespace OpenSim.Region.CoreModules.Asset
335 return asset; 348 return asset;
336 } 349 }
337 350
351 private bool CheckFromMemoryCache(string id)
352 {
353 AssetBase asset = null;
354
355 if (m_MemoryCache.TryGetValue(id, out asset))
356 return true;
357
358 return false;
359 }
360
361
338 /// <summary> 362 /// <summary>
339 /// Try to get an asset from the file cache. 363 /// Try to get an asset from the file cache.
340 /// </summary> 364 /// </summary>
@@ -399,6 +423,7 @@ namespace OpenSim.Region.CoreModules.Asset
399 m_log.WarnFormat( 423 m_log.WarnFormat(
400 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 424 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
401 filename, id, e.Message, e.StackTrace); 425 filename, id, e.Message, e.StackTrace);
426
402 } 427 }
403 finally 428 finally
404 { 429 {
@@ -410,6 +435,50 @@ namespace OpenSim.Region.CoreModules.Asset
410 return asset; 435 return asset;
411 } 436 }
412 437
438 private bool CheckFromFileCache(string id)
439 {
440 bool found = false;
441
442 string filename = GetFileName(id);
443 if (File.Exists(filename))
444 {
445 // actually check if we can open it, and so update expire
446 FileStream stream = null;
447 try
448 {
449 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
450 if (stream != null)
451 {
452 found = true;
453 stream.Close();
454 }
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 }
470 catch (Exception e)
471 {
472 found = false;
473 m_log.ErrorFormat(
474 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
475 filename, id, e.Message, e.StackTrace);
476 }
477 }
478
479 return found;
480 }
481
413 public AssetBase Get(string id) 482 public AssetBase Get(string id)
414 { 483 {
415 m_Requests++; 484 m_Requests++;
@@ -446,11 +515,26 @@ namespace OpenSim.Region.CoreModules.Asset
446 return asset; 515 return asset;
447 } 516 }
448 517
518 public bool Check(string id)
519 {
520 if (m_MemoryCacheEnabled && CheckFromMemoryCache(id))
521 return true;
522
523 if (m_FileCacheEnabled && CheckFromFileCache(id))
524 return true;
525 return false;
526 }
527
449 public AssetBase GetCached(string id) 528 public AssetBase GetCached(string id)
450 { 529 {
451 return Get(id); 530 return Get(id);
452 } 531 }
453 532
533 public AssetBase CheckCached(string id)
534 {
535 return Get(id);
536 }
537
454 public void Expire(string id) 538 public void Expire(string id)
455 { 539 {
456 if (m_LogLevel >= 2) 540 if (m_LogLevel >= 2)
@@ -966,6 +1050,11 @@ namespace OpenSim.Region.CoreModules.Asset
966 return asset.Data; 1050 return asset.Data;
967 } 1051 }
968 1052
1053 public bool CheckData(string id)
1054 {
1055 return Check(id); ;
1056 }
1057
969 public bool Get(string id, object sender, AssetRetrieved handler) 1058 public bool Get(string id, object sender, AssetRetrieved handler)
970 { 1059 {
971 AssetBase asset = Get(id); 1060 AssetBase asset = Get(id);
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index 9592ca0..ce9b546 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.Asset
115 // IImprovedAssetCache 115 // IImprovedAssetCache
116 // 116 //
117 117
118 public bool Check(string id)
119 {
120 return false;
121 }
122
118 public void Cache(AssetBase asset) 123 public void Cache(AssetBase asset)
119 { 124 {
120 if (asset != null) 125 if (asset != null)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 675fccc..62b25d0 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 43using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Services.Interfaces;
44 45
45namespace OpenSim.Region.CoreModules.Avatar.Attachments 46namespace OpenSim.Region.CoreModules.Avatar.Attachments
46{ 47{
@@ -295,6 +296,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
295 if (DebugLevel > 0) 296 if (DebugLevel > 0)
296 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); 297 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
297 298
299 XmlDocument doc = new XmlDocument();
300 string stateData = String.Empty;
301
302 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
303 if (attServ != null)
304 {
305 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
306 stateData = attServ.Get(sp.UUID.ToString());
307 if (stateData != String.Empty)
308 {
309 try
310 {
311 doc.LoadXml(stateData);
312 }
313 catch { }
314 }
315 }
316
317 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
318
319 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
320 if (nodes.Count > 0)
321 {
322 foreach (XmlNode n in nodes)
323 {
324 XmlElement elem = (XmlElement)n;
325 string itemID = elem.GetAttribute("ItemID");
326 string xml = elem.InnerXml;
327
328 itemData[new UUID(itemID)] = xml;
329 }
330 }
331
332
298 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 333 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
299 foreach (AvatarAttachment attach in attachments) 334 foreach (AvatarAttachment attach in attachments)
300 { 335 {
@@ -314,11 +349,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
314 349
315 try 350 try
316 { 351 {
352 string xmlData;
353 XmlDocument d = null;
354 UUID asset;
355 if (itemData.TryGetValue(attach.ItemID, out xmlData))
356 {
357 d = new XmlDocument();
358 d.LoadXml(xmlData);
359 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
360 }
361
317 // 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
318 // inventory right now. 363 // inventory right now.
319 SceneObjectGroup objatt 364 SceneObjectGroup objatt
320 = RezSingleAttachmentFromInventoryInternal( 365 = RezSingleAttachmentFromInventoryInternal(
321 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); 366 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
367
368
369 if (ThrottlePer100PrimsRezzed > 0)
370 {
371 int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
372
373 if (DebugLevel > 0)
374 m_log.DebugFormat(
375 "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
376 throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
377
378 Thread.Sleep(throttleMs);
379 }
322 } 380 }
323 catch (Exception e) 381 catch (Exception e)
324 { 382 {
@@ -381,13 +439,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
381 sp.ClearAttachments(); 439 sp.ClearAttachments();
382 } 440 }
383 441
384 public bool AttachObject( 442 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
385 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append)
386 { 443 {
387 if (!Enabled) 444 if (!Enabled)
388 return false; 445 return false;
389 446
390 return AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append); 447 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
391 } 448 }
392 449
393 /// <summary> 450 /// <summary>
@@ -400,10 +457,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
400 /// <param name='silent'></param> 457 /// <param name='silent'></param>
401 /// <param name='addToInventory'>If true then add object to user inventory.</param> 458 /// <param name='addToInventory'>If true then add object to user inventory.</param>
402 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> 459 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
403 /// <param name='append'>Append to attachment point rather than replace.</param> 460 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
404 private bool AttachObjectInternal(
405 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append)
406 { 461 {
462// m_log.DebugFormat(
463// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
464// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
465
466 if (sp.GetAttachments().Contains(group))
467 {
468// m_log.WarnFormat(
469// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
470// group.Name, group.LocalId, sp.Name, AttachmentPt);
471
472 return false;
473 }
474
407 if (group.GetSittingAvatarsCount() != 0) 475 if (group.GetSittingAvatarsCount() != 0)
408 { 476 {
409 if (DebugLevel > 0) 477 if (DebugLevel > 0)
@@ -415,6 +483,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
415 } 483 }
416 484
417 Vector3 attachPos = group.AbsolutePosition; 485 Vector3 attachPos = group.AbsolutePosition;
486
487 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
488 // be removed when that functionality is implemented in opensim
489 attachmentPt &= 0x7f;
490
418 // If the attachment point isn't the same as the one previously used 491 // If the attachment point isn't the same as the one previously used
419 // set it's offset position = 0 so that it appears on the attachment point 492 // set it's offset position = 0 so that it appears on the attachment point
420 // and not in a weird location somewhere unknown. 493 // and not in a weird location somewhere unknown.
@@ -423,7 +496,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
423 attachPos = Vector3.Zero; 496 attachPos = Vector3.Zero;
424 } 497 }
425 498
426 // AttachmentPt 0 means the client chose to 'wear' the attachment. 499 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment.
427 if (attachmentPt == (uint)AttachmentPoint.Default) 500 if (attachmentPt == (uint)AttachmentPoint.Default)
428 { 501 {
429 // Check object for stored attachment point 502 // Check object for stored attachment point
@@ -438,9 +511,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
438 attachPos = Vector3.Zero; 511 attachPos = Vector3.Zero;
439 } 512 }
440 513
441 group.AttachmentPoint = attachmentPt;
442 group.AbsolutePosition = attachPos;
443
444 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 514 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
445 515
446 if (attachments.Contains(group)) 516 if (attachments.Contains(group))
@@ -473,6 +543,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
473 543
474 lock (sp.AttachmentsSyncLock) 544 lock (sp.AttachmentsSyncLock)
475 { 545 {
546 group.AttachmentPoint = attachmentPt;
547 group.AbsolutePosition = attachPos;
548
476 if (addToInventory && sp.PresenceType != PresenceType.Npc) 549 if (addToInventory && sp.PresenceType != PresenceType.Npc)
477 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); 550 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
478 551
@@ -503,7 +576,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
503 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 576 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
504 } 577 }
505 578
506 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 579 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
580 {
581 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
582 }
583
584 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
507 { 585 {
508 if (!Enabled) 586 if (!Enabled)
509 return null; 587 return null;
@@ -541,7 +619,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
541 bool append = (AttachmentPt & 0x80) != 0; 619 bool append = (AttachmentPt & 0x80) != 0;
542 AttachmentPt &= 0x7f; 620 AttachmentPt &= 0x7f;
543 621
544 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); 622 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
545 } 623 }
546 624
547 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 625 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -618,7 +696,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
618 so.AttachedAvatar = UUID.Zero; 696 so.AttachedAvatar = UUID.Zero;
619 rootPart.SetParentLocalId(0); 697 rootPart.SetParentLocalId(0);
620 so.ClearPartAttachmentData(); 698 so.ClearPartAttachmentData();
621 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); 699 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive,false);
622 so.HasGroupChanged = true; 700 so.HasGroupChanged = true;
623 rootPart.Rezzed = DateTime.Now; 701 rootPart.Rezzed = DateTime.Now;
624 rootPart.RemFlag(PrimFlags.TemporaryOnRez); 702 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
@@ -951,7 +1029,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
951 } 1029 }
952 1030
953 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 1031 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
954 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) 1032 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
955 { 1033 {
956 if (m_invAccessModule == null) 1034 if (m_invAccessModule == null)
957 return null; 1035 return null;
@@ -995,7 +1073,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
995 // This will throw if the attachment fails 1073 // This will throw if the attachment fails
996 try 1074 try
997 { 1075 {
998 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); 1076 if (doc != null)
1077 {
1078 objatt.LoadScriptState(doc);
1079 objatt.ResetOwnerChangeFlag();
1080 }
1081
1082 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
999 } 1083 }
1000 catch (Exception e) 1084 catch (Exception e)
1001 { 1085 {
@@ -1149,7 +1233,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1149 AttachmentPt &= 0x7f; 1233 AttachmentPt &= 0x7f;
1150 1234
1151 // Calls attach with a Zero position 1235 // Calls attach with a Zero position
1152 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) 1236 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, true, append))
1153 { 1237 {
1154 if (DebugLevel > 0) 1238 if (DebugLevel > 0)
1155 m_log.Debug( 1239 m_log.Debug(
@@ -1211,4 +1295,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1211 1295
1212 #endregion 1296 #endregion
1213 } 1297 }
1214} \ No newline at end of file 1298}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index f4bf6b3..35045b5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -201,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
201 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 201 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
202 202
203 m_numberOfAttachEventsFired = 0; 203 m_numberOfAttachEventsFired = 0;
204 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 204 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
205 205
206 // Check status on scene presence 206 // Check status on scene presence
207 Assert.That(sp.HasAttachments(), Is.True); 207 Assert.That(sp.HasAttachments(), Is.True);
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
248 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); 248 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
249 249
250 m_numberOfAttachEventsFired = 0; 250 m_numberOfAttachEventsFired = 0;
251 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false); 251 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false);
252 252
253 // Check status on scene presence 253 // Check status on scene presence
254 Assert.That(sp.HasAttachments(), Is.True); 254 Assert.That(sp.HasAttachments(), Is.True);
@@ -281,7 +281,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
281 281
282 // Test wearing a different attachment from the ground. 282 // Test wearing a different attachment from the ground.
283 { 283 {
284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
285 285
286 // Check status on scene presence 286 // Check status on scene presence
287 Assert.That(sp.HasAttachments(), Is.True); 287 Assert.That(sp.HasAttachments(), Is.True);
@@ -314,7 +314,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
314 314
315 // Test rewearing an already worn attachment from ground. Nothing should happen. 315 // Test rewearing an already worn attachment from ground. Nothing should happen.
316 { 316 {
317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
318 318
319 // Check status on scene presence 319 // Check status on scene presence
320 Assert.That(sp.HasAttachments(), Is.True); 320 Assert.That(sp.HasAttachments(), Is.True);
@@ -372,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
372 sp2.AbsolutePosition = new Vector3(0, 0, 0); 372 sp2.AbsolutePosition = new Vector3(0, 0, 0);
373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
374 374
375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
376 376
377 Assert.That(sp.HasAttachments(), Is.False); 377 Assert.That(sp.HasAttachments(), Is.False);
378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -667,7 +667,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
667 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 667 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
668 668
669 SceneObjectGroup rezzedSo 669 SceneObjectGroup rezzedSo
670 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 670 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
671 671
672 // Wait for chat to signal rezzed script has been started. 672 // Wait for chat to signal rezzed script has been started.
673 m_chatEvent.WaitOne(60000); 673 m_chatEvent.WaitOne(60000);
@@ -686,7 +686,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
686 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 686 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
687 687
688 // Re-rez the attachment to check script running state 688 // Re-rez the attachment to check script running state
689 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 689 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
690 690
691 // Wait for chat to signal rezzed script has been started. 691 // Wait for chat to signal rezzed script has been started.
692 m_chatEvent.WaitOne(60000); 692 m_chatEvent.WaitOne(60000);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index aea768e..09cc998 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -145,33 +145,37 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
145 /// <param name="sp"></param> 145 /// <param name="sp"></param>
146 /// <param name="texture"></param> 146 /// <param name="texture"></param>
147 /// <param name="visualParam"></param> 147 /// <param name="visualParam"></param>
148 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) 148 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems)
149 { 149 {
150 DoSetAppearance(sp, appearance.Texture, appearance.VisualParams, new List<CachedTextureRequestArg>()); 150 SetAppearance(sp, appearance.Texture, appearance.VisualParams, cacheItems);
151 } 151 }
152 152
153 /// <summary> 153
154 /// Set appearance data (texture asset IDs and slider settings) 154 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
155 /// </summary>
156 /// <param name="sp"></param>
157 /// <param name="texture"></param>
158 /// <param name="visualParam"></param>
159 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
160 { 155 {
161 DoSetAppearance(sp, textureEntry, visualParams, new List<CachedTextureRequestArg>()); 156 float oldoff = sp.Appearance.AvatarFeetOffset;
157 Vector3 oldbox = sp.Appearance.AvatarBoxSize;
158
159 SetAppearance(sp, textureEntry, visualParams, cacheItems);
160 sp.Appearance.SetSize(avSize);
161
162 float off = sp.Appearance.AvatarFeetOffset;
163 Vector3 box = sp.Appearance.AvatarBoxSize;
164 if (oldoff != off || oldbox != box)
165 ((ScenePresence)sp).SetSize(box, off);
162 } 166 }
163 167
164 /// <summary> 168 /// <summary>
165 /// Set appearance data (texture asset IDs and slider settings) 169 /// Set appearance data (texture asset IDs and slider settings)
166 /// </summary> 170 /// </summary>
167 /// <param name="sp"></param> 171 /// <param name="sp"></param>
168 /// <param name="texture"></param> 172 /// <param name="texture"></param>
169 /// <param name="visualParam"></param> 173 /// <param name="visualParam"></param>
170 protected void DoSetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> hashes) 174 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems)
171 { 175 {
172 // m_log.DebugFormat( 176// m_log.DebugFormat(
173 // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", 177// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
174 // sp.Name, textureEntry, visualParams); 178// sp.Name, textureEntry, visualParams);
175 179
176 // TODO: This is probably not necessary any longer, just assume the 180 // TODO: This is probably not necessary any longer, just assume the
177 // textureEntry set implies that the appearance transaction is complete 181 // textureEntry set implies that the appearance transaction is complete
@@ -190,36 +194,38 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
190 // m_log.DebugFormat( 194 // m_log.DebugFormat(
191 // "[AVFACTORY]: Setting visual params for {0} to {1}", 195 // "[AVFACTORY]: Setting visual params for {0} to {1}",
192 // client.Name, string.Join(", ", visualParamsStrings)); 196 // client.Name, string.Join(", ", visualParamsStrings));
193 197/*
194 float oldHeight = sp.Appearance.AvatarHeight; 198 float oldHeight = sp.Appearance.AvatarHeight;
195 changed = sp.Appearance.SetVisualParams(visualParams); 199 changed = sp.Appearance.SetVisualParams(visualParams);
196 200
197 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) 201 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
198 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); 202 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
199 } 203 */
204// float oldoff = sp.Appearance.AvatarFeetOffset;
205// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
206 changed = sp.Appearance.SetVisualParams(visualParams);
207// float off = sp.Appearance.AvatarFeetOffset;
208// Vector3 box = sp.Appearance.AvatarBoxSize;
209// if(oldoff != off || oldbox != box)
210// ((ScenePresence)sp).SetSize(box,off);
200 211
212 }
213
201 // Process the baked texture array 214 // Process the baked texture array
202 if (textureEntry != null) 215 if (textureEntry != null)
203 { 216 {
204 // m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); 217 m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);
205 // WriteBakedTexturesReport(sp, m_log.DebugFormat); 218
219// WriteBakedTexturesReport(sp, m_log.DebugFormat);
206 220
207 changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; 221 changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
208 222
209 // WriteBakedTexturesReport(sp, m_log.DebugFormat); 223// WriteBakedTexturesReport(sp, m_log.DebugFormat);
210 224
211 // If bake textures are missing and this is not an NPC, request a rebake from client 225 // If bake textures are missing and this is not an NPC, request a rebake from client
212 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) 226 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
213 RequestRebake(sp, true); 227 RequestRebake(sp, true);
214 228
215 // Save the wearble hashes in the appearance
216 sp.Appearance.ResetTextureHashes();
217 if (m_reusetextures)
218 {
219 foreach (CachedTextureRequestArg arg in hashes)
220 sp.Appearance.SetTextureHash(arg.BakedTextureIndex,arg.WearableHashID);
221 }
222
223 // This appears to be set only in the final stage of the appearance 229 // This appears to be set only in the final stage of the appearance
224 // update transaction. In theory, we should be able to do an immediate 230 // update transaction. In theory, we should be able to do an immediate
225 // appearance send and save here. 231 // appearance send and save here.
@@ -253,13 +259,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
253 259
254 public bool SendAppearance(UUID agentId) 260 public bool SendAppearance(UUID agentId)
255 { 261 {
256 // m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); 262// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
257 263
258 ScenePresence sp = m_scene.GetScenePresence(agentId); 264 ScenePresence sp = m_scene.GetScenePresence(agentId);
259 if (sp == null) 265 if (sp == null)
260 { 266 {
261 // This is expected if the user has gone away. 267 // This is expected if the user has gone away.
262 // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); 268// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
263 return false; 269 return false;
264 } 270 }
265 271
@@ -277,6 +283,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
277 return GetBakedTextureFaces(sp); 283 return GetBakedTextureFaces(sp);
278 } 284 }
279 285
286 public WearableCacheItem[] GetCachedItems(UUID agentId)
287 {
288 ScenePresence sp = m_scene.GetScenePresence(agentId);
289 WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
290 //foreach (WearableCacheItem item in items)
291 //{
292
293 //}
294 return items;
295 }
296
280 public bool SaveBakedTextures(UUID agentId) 297 public bool SaveBakedTextures(UUID agentId)
281 { 298 {
282 ScenePresence sp = m_scene.GetScenePresence(agentId); 299 ScenePresence sp = m_scene.GetScenePresence(agentId);
@@ -336,7 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
336 /// <param name="agentId"></param> 353 /// <param name="agentId"></param>
337 public void QueueAppearanceSend(UUID agentid) 354 public void QueueAppearanceSend(UUID agentid)
338 { 355 {
339 // m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); 356// m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
340 357
341 // 10000 ticks per millisecond, 1000 milliseconds per second 358 // 10000 ticks per millisecond, 1000 milliseconds per second
342 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); 359 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
@@ -349,7 +366,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
349 366
350 public void QueueAppearanceSave(UUID agentid) 367 public void QueueAppearanceSave(UUID agentid)
351 { 368 {
352 // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); 369// m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid);
353 370
354 // 10000 ticks per millisecond, 1000 milliseconds per second 371 // 10000 ticks per millisecond, 1000 milliseconds per second
355 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); 372 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
@@ -363,6 +380,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
363 public bool ValidateBakedTextureCache(IScenePresence sp) 380 public bool ValidateBakedTextureCache(IScenePresence sp)
364 { 381 {
365 bool defonly = true; // are we only using default textures 382 bool defonly = true; // are we only using default textures
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
385 WearableCacheItem[] wearableCache = null;
386
387 // Cache wearable data for teleport.
388 // Only makes sense if there's a bake module and a cache module
389 if (bakedModule != null && cache != null)
390 {
391 try
392 {
393 wearableCache = bakedModule.Get(sp.UUID);
394 }
395 catch (Exception)
396 {
397
398 }
399 if (wearableCache != null)
400 {
401 for (int i = 0; i < wearableCache.Length; i++)
402 {
403 cache.Cache(wearableCache[i].TextureAsset);
404 }
405 }
406 }
407 /*
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
409 if (invService.GetRootFolder(userID) != null)
410 {
411 WearableCacheItem[] wearableCache = null;
412 if (bakedModule != null)
413 {
414 try
415 {
416 wearableCache = bakedModule.Get(userID);
417 appearance.WearableCacheItems = wearableCache;
418 appearance.WearableCacheItemsDirty = false;
419 foreach (WearableCacheItem item in wearableCache)
420 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID;
422 }
423 }
424 catch (Exception)
425 {
426
427 }
428 }
429 */
366 430
367 // Process the texture entry 431 // Process the texture entry
368 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 432 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
@@ -370,13 +434,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
370 int idx = AvatarAppearance.BAKE_INDICES[i]; 434 int idx = AvatarAppearance.BAKE_INDICES[i];
371 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; 435 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
372 436
373 // if there is no texture entry, skip it 437 // No face, so lets check our baked service cache, teleport or login.
374 if (face == null) 438 if (face == null)
375 continue; 439 {
440 if (wearableCache != null)
441 {
442 // If we find the an appearance item, set it as the textureentry and the face
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache);
444 if (searchitem != null)
445 {
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID;
448 face = sp.Appearance.Texture.FaceTextures[idx];
449 }
450 else
451 {
452 // if there is no texture entry and no baked cache, skip it
453 continue;
454 }
455 }
456 else
457 {
458 //No texture entry face and no cache. Skip this face.
459 continue;
460 }
461 }
462
376 463
377 // m_log.DebugFormat( 464// m_log.DebugFormat(
378 // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", 465// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
379 // face.TextureID, idx, client.Name, client.AgentId); 466// face.TextureID, idx, client.Name, client.AgentId);
380 467
381 // if the texture is one of the "defaults" then skip it 468 // if the texture is one of the "defaults" then skip it
382 // this should probably be more intelligent (skirt texture doesnt matter 469 // this should probably be more intelligent (skirt texture doesnt matter
@@ -387,11 +474,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
387 474
388 defonly = false; // found a non-default texture reference 475 defonly = false; // found a non-default texture reference
389 476
390 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) 477 if (cache != null)
391 return false; 478 {
479 if (!cache.Check(face.TextureID.ToString()))
480 return false;
481 }
482 else
483 {
484 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
485 return false;
486 }
392 } 487 }
393 488
394 // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 489// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID);
395 490
396 // If we only found default textures, then the appearance is not cached 491 // If we only found default textures, then the appearance is not cached
397 return (defonly ? false : true); 492 return (defonly ? false : true);
@@ -400,6 +495,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
400 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 495 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
401 { 496 {
402 int texturesRebaked = 0; 497 int texturesRebaked = 0;
498 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
403 499
404 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 500 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
405 { 501 {
@@ -410,9 +506,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
410 if (face == null) 506 if (face == null)
411 continue; 507 continue;
412 508
413 // m_log.DebugFormat( 509// m_log.DebugFormat(
414 // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", 510// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
415 // face.TextureID, idx, client.Name, client.AgentId); 511// face.TextureID, idx, client.Name, client.AgentId);
416 512
417 // if the texture is one of the "defaults" then skip it 513 // if the texture is one of the "defaults" then skip it
418 // this should probably be more intelligent (skirt texture doesnt matter 514 // this should probably be more intelligent (skirt texture doesnt matter
@@ -423,21 +519,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
423 519
424 if (missingTexturesOnly) 520 if (missingTexturesOnly)
425 { 521 {
426 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 522 if (cache != null)
427 { 523 {
428 continue; 524 if (cache.Check(face.TextureID.ToString()))
525 continue;
526 else
527 {
528 m_log.DebugFormat(
529 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
530 face.TextureID, idx, sp.Name);
531 }
429 } 532 }
430 else 533 else
431 { 534 {
432 // On inter-simulator teleports, this occurs if baked textures are not being stored by the 535 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null)
433 // grid asset service (which means that they are not available to the new region and so have 536 {
434 // to be re-requested from the client). 537 continue;
435 // 538 }
436 // The only available core OpenSimulator behaviour right now 539
437 // is not to store these textures, temporarily or otherwise. 540 else
438 m_log.DebugFormat( 541 {
439 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 542 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
440 face.TextureID, idx, sp.Name); 543 // grid asset service (which means that they are not available to the new region and so have
544 // to be re-requested from the client).
545 //
546 // The only available core OpenSimulator behaviour right now
547 // is not to store these textures, temporarily or otherwise.
548 m_log.DebugFormat(
549 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
550 face.TextureID, idx, sp.Name);
551 }
441 } 552 }
442 } 553 }
443 else 554 else
@@ -476,9 +587,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
476 if (bakeType == BakeType.Unknown) 587 if (bakeType == BakeType.Unknown)
477 continue; 588 continue;
478 589
479 // m_log.DebugFormat( 590// m_log.DebugFormat(
480 // "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}", 591// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
481 // acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); 592// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
482 593
483 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); 594 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
484 Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture 595 Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture
@@ -502,7 +613,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
502 UUID avatarID = kvp.Key; 613 UUID avatarID = kvp.Key;
503 long sendTime = kvp.Value; 614 long sendTime = kvp.Value;
504 615
505 // m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now); 616// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
506 617
507 if (sendTime < now) 618 if (sendTime < now)
508 { 619 {
@@ -548,11 +659,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
548 if (sp == null) 659 if (sp == null)
549 { 660 {
550 // This is expected if the user has gone away. 661 // This is expected if the user has gone away.
551 // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); 662// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
552 return; 663 return;
553 } 664 }
554 665
555 // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); 666// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
556 667
557 // This could take awhile since it needs to pull inventory 668 // This could take awhile since it needs to pull inventory
558 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape 669 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
@@ -579,26 +690,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
579 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) 690 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
580 { 691 {
581 IInventoryService invService = m_scene.InventoryService; 692 IInventoryService invService = m_scene.InventoryService;
582 693 bool resetwearable = false;
583 if (invService.GetRootFolder(userID) != null) 694 if (invService.GetRootFolder(userID) != null)
584 { 695 {
585 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 696 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
586 { 697 {
587 for (int j = 0; j < appearance.Wearables[i].Count; j++) 698 for (int j = 0; j < appearance.Wearables[i].Count; j++)
588 { 699 {
700 // Check if the default wearables are not set
589 if (appearance.Wearables[i][j].ItemID == UUID.Zero) 701 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
702 {
703 switch ((WearableType) i)
704 {
705 case WearableType.Eyes:
706 case WearableType.Hair:
707 case WearableType.Shape:
708 case WearableType.Skin:
709 //case WearableType.Underpants:
710 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
711 resetwearable = true;
712 m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values.");
713 resetwearable = true;
714 break;
715
716 }
590 continue; 717 continue;
718 }
591 719
592 // Ignore ruth's assets 720 // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1
593 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 721 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
722 {
723 switch ((WearableType)i)
724 {
725 case WearableType.Eyes:
726 case WearableType.Hair:
727 case WearableType.Shape:
728 case WearableType.Skin:
729 //case WearableType.Underpants:
730 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
731
732 m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
733 resetwearable = true;
734 break;
735
736 }
594 continue; 737 continue;
595 738 }
739
596 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 740 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
597 baseItem = invService.GetItem(baseItem); 741 baseItem = invService.GetItem(baseItem);
598 742
599 if (baseItem != null) 743 if (baseItem != null)
600 { 744 {
601 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); 745 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
746 int unmodifiedWearableIndexForClosure = i;
747 m_scene.AssetService.Get(baseItem.AssetID.ToString(), this,
748 delegate(string x, object y, AssetBase z)
749 {
750 if (z == null)
751 {
752 TryAndRepairBrokenWearable(
753 (WearableType)unmodifiedWearableIndexForClosure, invService,
754 userID, appearance);
755 }
756 });
602 } 757 }
603 else 758 else
604 { 759 {
@@ -606,17 +761,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
606 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", 761 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
607 appearance.Wearables[i][j].ItemID, (WearableType)i); 762 appearance.Wearables[i][j].ItemID, (WearableType)i);
608 763
609 appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); 764 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
765 resetwearable = true;
766
610 } 767 }
611 } 768 }
612 } 769 }
770
771 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
772 if (appearance.Wearables[(int) WearableType.Eyes] == null)
773 {
774 m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
775
776 TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
777 resetwearable = true;
778 }
779 else
780 {
781 if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero)
782 {
783 m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}",
784 appearance.Wearables[(int) WearableType.Eyes][0].ItemID,
785 appearance.Wearables[(int) WearableType.Eyes][0].AssetID);
786 TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
787 resetwearable = true;
788
789 }
790
791 }
792 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
793 if (appearance.Wearables[(int)WearableType.Shape] == null)
794 {
795 m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape));
796
797 TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
798 resetwearable = true;
799 }
800 else
801 {
802 if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero)
803 {
804 m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}",
805 appearance.Wearables[(int)WearableType.Shape][0].ItemID,
806 appearance.Wearables[(int)WearableType.Shape][0].AssetID);
807 TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
808 resetwearable = true;
809
810 }
811
812 }
813 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
814 if (appearance.Wearables[(int)WearableType.Hair] == null)
815 {
816 m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair));
817
818 TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
819 resetwearable = true;
820 }
821 else
822 {
823 if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero)
824 {
825 m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}",
826 appearance.Wearables[(int)WearableType.Hair][0].ItemID,
827 appearance.Wearables[(int)WearableType.Hair][0].AssetID);
828 TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
829 resetwearable = true;
830
831 }
832
833 }
834 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
835 if (appearance.Wearables[(int)WearableType.Skin] == null)
836 {
837 m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin));
838
839 TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
840 resetwearable = true;
841 }
842 else
843 {
844 if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero)
845 {
846 m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}",
847 appearance.Wearables[(int)WearableType.Skin][0].ItemID,
848 appearance.Wearables[(int)WearableType.Skin][0].AssetID);
849 TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
850 resetwearable = true;
851
852 }
853
854 }
855 if (resetwearable)
856 {
857 ScenePresence presence = null;
858 if (m_scene.TryGetScenePresence(userID, out presence))
859 {
860 presence.ControllingClient.SendWearables(presence.Appearance.Wearables,
861 presence.Appearance.Serial++);
862 }
863 }
864
613 } 865 }
614 else 866 else
615 { 867 {
616 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); 868 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
617 } 869 }
618 } 870 }
871 private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance)
872 {
873 UUID defaultwearable = GetDefaultItem(type);
874 if (defaultwearable != UUID.Zero)
875 {
876 UUID newInvItem = UUID.Random();
877 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
878 {
879 AssetID =
880 defaultwearable,
881 AssetType
882 =
883 (int)
884 AssetType
885 .Bodypart,
886 CreatorId
887 =
888 userID
889 .ToString
890 (),
891 //InvType = (int)InventoryType.Wearable,
892
893 Description
894 =
895 "Failed Wearable Replacement",
896 Folder =
897 invService
898 .GetFolderForType
899 (userID,
900 AssetType
901 .Bodypart)
902 .ID,
903 Flags = (uint) type,
904 Name = Enum.GetName(typeof (WearableType), type),
905 BasePermissions = (uint) PermissionMask.Copy,
906 CurrentPermissions = (uint) PermissionMask.Copy,
907 EveryOnePermissions = (uint) PermissionMask.Copy,
908 GroupPermissions = (uint) PermissionMask.Copy,
909 NextPermissions = (uint) PermissionMask.Copy
910 };
911 invService.AddItem(itembase);
912 UUID LinkInvItem = UUID.Random();
913 itembase = new InventoryItemBase(LinkInvItem, userID)
914 {
915 AssetID =
916 newInvItem,
917 AssetType
918 =
919 (int)
920 AssetType
921 .Link,
922 CreatorId
923 =
924 userID
925 .ToString
926 (),
927 InvType = (int) InventoryType.Wearable,
928
929 Description
930 =
931 "Failed Wearable Replacement",
932 Folder =
933 invService
934 .GetFolderForType
935 (userID,
936 AssetType
937 .CurrentOutfitFolder)
938 .ID,
939 Flags = (uint) type,
940 Name = Enum.GetName(typeof (WearableType), type),
941 BasePermissions = (uint) PermissionMask.Copy,
942 CurrentPermissions = (uint) PermissionMask.Copy,
943 EveryOnePermissions = (uint) PermissionMask.Copy,
944 GroupPermissions = (uint) PermissionMask.Copy,
945 NextPermissions = (uint) PermissionMask.Copy
946 };
947 invService.AddItem(itembase);
948 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
949 ScenePresence presence = null;
950 if (m_scene.TryGetScenePresence(userID, out presence))
951 {
952 m_scene.SendInventoryUpdate(presence.ControllingClient,
953 invService.GetFolderForType(userID,
954 AssetType
955 .CurrentOutfitFolder),
956 false, true);
957 }
958 }
959 }
960 private UUID GetDefaultItem(WearableType wearable)
961 {
962 // These are ruth
963 UUID ret = UUID.Zero;
964 switch (wearable)
965 {
966 case WearableType.Eyes:
967 ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7");
968 break;
969 case WearableType.Hair:
970 ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66");
971 break;
972 case WearableType.Pants:
973 ret = new UUID("00000000-38f9-1111-024e-222222111120");
974 break;
975 case WearableType.Shape:
976 ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
977 break;
978 case WearableType.Shirt:
979 ret = new UUID("00000000-38f9-1111-024e-222222111110");
980 break;
981 case WearableType.Skin:
982 ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb");
983 break;
984 case WearableType.Undershirt:
985 ret = new UUID("16499ebb-3208-ec27-2def-481881728f47");
986 break;
987 case WearableType.Underpants:
988 ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d");
989 break;
990 }
619 991
992 return ret;
993 }
620 #endregion 994 #endregion
621 995
622 #region Client Event Handlers 996 #region Client Event Handlers
@@ -626,12 +1000,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
626 /// <param name="client"></param> 1000 /// <param name="client"></param>
627 private void Client_OnRequestWearables(IClientAPI client) 1001 private void Client_OnRequestWearables(IClientAPI client)
628 { 1002 {
629 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); 1003 Util.FireAndForget(delegate(object x)
630 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 1004 {
631 if (sp != null) 1005 Thread.Sleep(4000);
632 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); 1006
633 else 1007 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId);
634 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); 1008 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
1009 if (sp != null)
1010 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
1011 else
1012 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
1013 });
635 } 1014 }
636 1015
637 /// <summary> 1016 /// <summary>
@@ -640,12 +1019,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
640 /// <param name="client"></param> 1019 /// <param name="client"></param>
641 /// <param name="texture"></param> 1020 /// <param name="texture"></param>
642 /// <param name="visualParam"></param> 1021 /// <param name="visualParam"></param>
643 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> hashes) 1022 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
644 { 1023 {
645 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); 1024 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
646 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 1025 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
647 if (sp != null) 1026 if (sp != null)
648 DoSetAppearance(sp, textureEntry, visualParams, hashes); 1027 SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems);
649 else 1028 else
650 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); 1029 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
651 } 1030 }
@@ -702,7 +1081,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
702 /// <param name="cachedTextureRequest"></param> 1081 /// <param name="cachedTextureRequest"></param>
703 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest) 1082 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
704 { 1083 {
705 // m_log.DebugFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId); 1084 // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
706 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 1085 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
707 1086
708 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>(); 1087 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
@@ -713,20 +1092,23 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
713 1092
714 if (m_reusetextures) 1093 if (m_reusetextures)
715 { 1094 {
716 if (sp.Appearance.GetTextureHash(index) == request.WearableHashID) 1095 // this is the most insanely dumb way to do this... however it seems to
717 { 1096 // actually work. if the appearance has been reset because wearables have
718 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index]; 1097 // changed then the texture entries are zero'd out until the bakes are
719 if (face != null) 1098 // uploaded. on login, if the textures exist in the cache (eg if you logged
720 texture = face.TextureID; 1099 // into the simulator recently, then the appearance will pull those and send
721 } 1100 // them back in the packet and you won't have to rebake. if the textures aren't
722 else 1101 // in the cache then the intial makeroot() call in scenepresence will zero
723 { 1102 // them out.
724 // We know that that hash is wrong, null it out 1103 //
725 // and wait for the setappearance call 1104 // a better solution (though how much better is an open question) is to
726 sp.Appearance.SetTextureHash(index,UUID.Zero); 1105 // store the hashes in the appearance and compare them. Thats's coming.
727 } 1106
728 1107 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
729 // m_log.WarnFormat("[AVFACTORY]: use texture {0} for index {1}; hash={2}",texture,index,request.WearableHashID); 1108 if (face != null)
1109 texture = face.TextureID;
1110
1111 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
730 } 1112 }
731 1113
732 CachedTextureResponseArg response = new CachedTextureResponseArg(); 1114 CachedTextureResponseArg response = new CachedTextureResponseArg();
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 1830d41..f090e15 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
61 for (byte i = 0; i < visualParams.Length; i++) 61 for (byte i = 0; i < visualParams.Length; i++)
62 visualParams[i] = i; 62 visualParams[i] = i;
63 63
64 afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); 64 afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams, new WearableCacheItem[0]);
65 65
66 // TODO: Check baked texture 66 // TODO: Check baked texture
67 Assert.AreEqual(visualParams, sp.Appearance.VisualParams); 67 Assert.AreEqual(visualParams, sp.Appearance.VisualParams);
@@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
102 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 102 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
103 eyesFace.TextureID = eyesTextureId; 103 eyesFace.TextureID = eyesTextureId;
104 104
105 afm.SetAppearance(sp, bakedTextureEntry, visualParams); 105 afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
106 afm.SaveBakedTextures(userId); 106 afm.SaveBakedTextures(userId);
107// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 107// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
108 108
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 58f747b..174642d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -50,7 +50,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
50 private int m_saydistance = 20; 50 private int m_saydistance = 20;
51 private int m_shoutdistance = 100; 51 private int m_shoutdistance = 100;
52 private int m_whisperdistance = 10; 52 private int m_whisperdistance = 10;
53 53 private List<Scene> m_scenes = new List<Scene>();
54 private List<string> FreezeCache = new List<string>();
55 private string m_adminPrefix = "";
54 internal object m_syncy = new object(); 56 internal object m_syncy = new object();
55 57
56 internal IConfig m_config; 58 internal IConfig m_config;
@@ -77,16 +79,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
77 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 79 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
78 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 80 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
79 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 81 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
82 m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", "");
80 } 83 }
81 84
82 public virtual void AddRegion(Scene scene) 85 public virtual void AddRegion(Scene scene)
83 { 86 {
84 if (!m_enabled) 87 if (!m_enabled) return;
85 return;
86 88
87 scene.EventManager.OnNewClient += OnNewClient; 89 lock (m_syncy)
88 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 90 {
89 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 91 if (!m_scenes.Contains(scene))
92 {
93 m_scenes.Add(scene);
94 scene.EventManager.OnNewClient += OnNewClient;
95 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
96 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
97 }
98 }
90 99
91 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 100 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
92 m_whisperdistance, m_saydistance, m_shoutdistance); 101 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -98,12 +107,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
98 107
99 public virtual void RemoveRegion(Scene scene) 108 public virtual void RemoveRegion(Scene scene)
100 { 109 {
101 if (!m_enabled) 110 if (!m_enabled) return;
102 return;
103 111
104 scene.EventManager.OnNewClient -= OnNewClient; 112 lock (m_syncy)
105 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 113 {
106 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 114 if (m_scenes.Contains(scene))
115 {
116 scene.EventManager.OnNewClient -= OnNewClient;
117 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
118 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
119 m_scenes.Remove(scene);
120 }
121 }
107 } 122 }
108 123
109 public virtual void Close() 124 public virtual void Close()
@@ -160,7 +175,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
160 return; 175 return;
161 } 176 }
162 177
163 DeliverChatToAvatars(ChatSourceType.Agent, c); 178 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
179 {
180 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
181 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
182 }
183 else
184 {
185 DeliverChatToAvatars(ChatSourceType.Agent, c);
186 }
164 } 187 }
165 188
166 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 189 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -174,11 +197,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
174 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 197 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
175 { 198 {
176 string fromName = c.From; 199 string fromName = c.From;
200 string fromNamePrefix = "";
177 UUID fromID = UUID.Zero; 201 UUID fromID = UUID.Zero;
178 UUID ownerID = UUID.Zero; 202 UUID ownerID = UUID.Zero;
179 UUID targetID = c.TargetUUID;
180 string message = c.Message; 203 string message = c.Message;
181 Scene scene = (Scene)c.Scene; 204 IScene scene = c.Scene;
205 UUID destination = c.Destination;
182 Vector3 fromPos = c.Position; 206 Vector3 fromPos = c.Position;
183 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, 207 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
184 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); 208 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
@@ -188,10 +212,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
188 switch (sourceType) 212 switch (sourceType)
189 { 213 {
190 case ChatSourceType.Agent: 214 case ChatSourceType.Agent:
191 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 215 if (!(scene is Scene))
216 {
217 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
218 scene.RegionInfo.RegionName, c.Sender.AgentId);
219 return;
220 }
221 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
192 fromPos = avatar.AbsolutePosition; 222 fromPos = avatar.AbsolutePosition;
193 fromName = avatar.Name; 223 fromName = avatar.Name;
194 fromID = c.Sender.AgentId; 224 fromID = c.Sender.AgentId;
225 if (avatar.GodLevel >= 200)
226 {
227 fromNamePrefix = m_adminPrefix;
228 }
229 destination = UUID.Zero; // Avatars cant "SayTo"
195 ownerID = c.Sender.AgentId; 230 ownerID = c.Sender.AgentId;
196 231
197 break; 232 break;
@@ -210,38 +245,48 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
210 message = message.Substring(0, 1000); 245 message = message.Substring(0, 1000);
211 246
212// m_log.DebugFormat( 247// m_log.DebugFormat(
213// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 248// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
214// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 249// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
215 250
216 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 251 HashSet<UUID> receiverIDs = new HashSet<UUID>();
217 252
218 if (targetID == UUID.Zero) 253 foreach (Scene s in m_scenes)
219 { 254 {
220 // This should use ForEachClient, but clients don't have a position. 255 // This should use ForEachClient, but clients don't have a position.
221 // If camera is moved into client, then camera position can be used 256 // If camera is moved into client, then camera position can be used
222 scene.ForEachScenePresence( 257 // MT: No, it can't, as chat is heard from the avatar position, not
258 // the camera position.
259 s.ForEachScenePresence(
223 delegate(ScenePresence presence) 260 delegate(ScenePresence presence)
224 { 261 {
225 if (TrySendChatMessage( 262 if (destination != UUID.Zero && presence.UUID != destination)
226 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 263 return;
227 receiverIDs.Add(presence.UUID); 264 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
265 if (Presencecheck != null)
266 {
267 // This will pass all chat from objects. Not
268 // perfect, but it will do. For now. Better
269 // than the prior behavior of muting all
270 // objects on a parcel with access restrictions
271 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
272 {
273 if (destination != UUID.Zero)
274 {
275 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
276 receiverIDs.Add(presence.UUID);
277 }
278 else
279 {
280 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
281 receiverIDs.Add(presence.UUID);
282 }
283 }
284 }
228 } 285 }
229 ); 286 );
230 } 287 }
231 else 288
232 { 289 (scene as Scene).EventManager.TriggerOnChatToClients(
233 // This is a send to a specific client eg from llRegionSayTo
234 // no need to check distance etc, jand send is as say
235 ScenePresence presence = scene.GetScenePresence(targetID);
236 if (presence != null && !presence.IsChildAgent)
237 {
238 if (TrySendChatMessage(
239 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
240 receiverIDs.Add(presence.UUID);
241 }
242 }
243
244 scene.EventManager.TriggerOnChatToClients(
245 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 290 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
246 } 291 }
247 292
@@ -280,28 +325,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
280 } 325 }
281 326
282 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 327 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
283
284 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 328 HashSet<UUID> receiverIDs = new HashSet<UUID>();
285 329
286 ((Scene)c.Scene).ForEachRootClient( 330 if (c.Scene != null)
287 delegate(IClientAPI client) 331 {
288 { 332 ((Scene)c.Scene).ForEachRootClient
289 // don't forward SayOwner chat from objects to 333 (
290 // non-owner agents 334 delegate(IClientAPI client)
291 if ((c.Type == ChatTypeEnum.Owner) && 335 {
292 (null != c.SenderObject) && 336 // don't forward SayOwner chat from objects to
293 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 337 // non-owner agents
294 return; 338 if ((c.Type == ChatTypeEnum.Owner) &&
295 339 (null != c.SenderObject) &&
296 client.SendChatMessage( 340 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
297 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, 341 return;
298 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 342
299 343 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
300 receiverIDs.Add(client.AgentId); 344 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
301 }); 345 receiverIDs.Add(client.AgentId);
302 346 }
303 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 347 );
304 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 348 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
349 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
350 }
305 } 351 }
306 352
307 /// <summary> 353 /// <summary>
@@ -326,21 +372,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
326 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
327 string message, ChatSourceType src, bool ignoreDistance) 373 string message, ChatSourceType src, bool ignoreDistance)
328 { 374 {
375 // don't send chat to child agents
376 if (presence.IsChildAgent) return false;
377
329 Vector3 fromRegionPos = fromPos + regionPos; 378 Vector3 fromRegionPos = fromPos + regionPos;
330 Vector3 toRegionPos = presence.AbsolutePosition + 379 Vector3 toRegionPos = presence.AbsolutePosition +
331 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, 380 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
332 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); 381 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
333 382
334 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 383 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
335 384
336 if (!ignoreDistance) 385 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
386 type == ChatTypeEnum.Say && dis > m_saydistance ||
387 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
337 { 388 {
338 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || 389 return false;
339 type == ChatTypeEnum.Say && dis > m_saydistance ||
340 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
341 {
342 return false;
343 }
344 } 390 }
345 391
346 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
@@ -350,5 +396,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
350 396
351 return true; 397 return true;
352 } 398 }
399
400 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
401 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
402 {
403 System.Threading.Timer Timer;
404 if (flags == 0)
405 {
406 FreezeCache.Add(target.ToString());
407 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
408 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
409 Timers.Add(target, Timer);
410 }
411 else
412 {
413 FreezeCache.Remove(target.ToString());
414 Timers.TryGetValue(target, out Timer);
415 Timers.Remove(target);
416 Timer.Dispose();
417 }
418 }
419
420 private void OnEndParcelFrozen(object avatar)
421 {
422 UUID target = (UUID)avatar;
423 FreezeCache.Remove(target.ToString());
424 System.Threading.Timer Timer;
425 Timers.TryGetValue(target, out Timer);
426 Timers.Remove(target);
427 Timer.Dispose();
428 }
353 } 429 }
354} \ No newline at end of file 430}
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index d26907b..0e7ab7e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -260,4 +260,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
260 return result; 260 return result;
261 } 261 }
262 } 262 }
263} \ No newline at end of file 263}
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 0cd495c..6b14fa6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -49,6 +49,8 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
49using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
50using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
51 51
52using Mono.Addins;
53
52namespace OpenSim.Region.CoreModules.Avatar.Gods 54namespace OpenSim.Region.CoreModules.Avatar.Gods
53{ 55{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")] 56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")]
@@ -62,6 +64,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
62 64
63 protected Scene m_scene; 65 protected Scene m_scene;
64 protected IDialogModule m_dialogModule; 66 protected IDialogModule m_dialogModule;
67
65 protected IDialogModule DialogModule 68 protected IDialogModule DialogModule
66 { 69 {
67 get 70 get
@@ -146,6 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
146 UUID godSessionID = userData["GodSessionID"].AsUUID(); 149 UUID godSessionID = userData["GodSessionID"].AsUUID();
147 uint kickFlags = userData["KickFlags"].AsUInteger(); 150 uint kickFlags = userData["KickFlags"].AsUInteger();
148 string reason = userData["Reason"].AsString(); 151 string reason = userData["Reason"].AsString();
152
149 ScenePresence god = m_scene.GetScenePresence(godID); 153 ScenePresence god = m_scene.GetScenePresence(godID);
150 if (god == null || god.ControllingClient.SessionId != godSessionID) 154 if (god == null || god.ControllingClient.SessionId != godSessionID)
151 return String.Empty; 155 return String.Empty;
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
deleted file mode 100644
index b735c61..0000000
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ /dev/null
@@ -1,260 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38using Mono.Addins;
39
40namespace OpenSim.Region.CoreModules.Avatar.Groups
41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
43 public class GroupsModule : ISharedRegionModule
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private Dictionary<UUID, GroupMembershipData> m_GroupMap =
49 new Dictionary<UUID, GroupMembershipData>();
50
51 private Dictionary<UUID, IClientAPI> m_ClientMap =
52 new Dictionary<UUID, IClientAPI>();
53
54 private UUID opensimulatorGroupID =
55 new UUID("00000000-68f9-1111-024e-222222111123");
56
57 private List<Scene> m_SceneList = new List<Scene>();
58
59 private static GroupMembershipData osGroup =
60 new GroupMembershipData();
61
62 private bool m_Enabled = false;
63
64 #region ISharedRegionModule Members
65
66 public void Initialise(IConfigSource config)
67 {
68 IConfig groupsConfig = config.Configs["Groups"];
69
70 if (groupsConfig == null)
71 {
72 m_log.Info("[GROUPS]: No configuration found. Using defaults");
73 }
74 else
75 {
76 m_Enabled = groupsConfig.GetBoolean("Enabled", false);
77 if (!m_Enabled)
78 {
79 m_log.Info("[GROUPS]: Groups disabled in configuration");
80 return;
81 }
82
83 if (groupsConfig.GetString("Module", "Default") != "Default")
84 {
85 m_Enabled = false;
86 return;
87 }
88 }
89
90 }
91
92 public void AddRegion(Scene scene)
93 {
94 if (!m_Enabled)
95 return;
96
97 lock (m_SceneList)
98 {
99 if (!m_SceneList.Contains(scene))
100 {
101 if (m_SceneList.Count == 0)
102 {
103 osGroup.GroupID = opensimulatorGroupID;
104 osGroup.GroupName = "OpenSimulator Testing";
105 osGroup.GroupPowers =
106 (uint)(GroupPowers.AllowLandmark |
107 GroupPowers.AllowSetHome);
108 m_GroupMap[opensimulatorGroupID] = osGroup;
109 }
110 m_SceneList.Add(scene);
111 }
112 }
113
114 scene.EventManager.OnNewClient += OnNewClient;
115 scene.EventManager.OnClientClosed += OnClientClosed;
116 // scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
117 }
118
119 public void RemoveRegion(Scene scene)
120 {
121 if (!m_Enabled)
122 return;
123
124 lock (m_SceneList)
125 {
126 if (m_SceneList.Contains(scene))
127 m_SceneList.Remove(scene);
128 }
129
130 scene.EventManager.OnNewClient -= OnNewClient;
131 scene.EventManager.OnClientClosed -= OnClientClosed;
132 }
133
134 public void RegionLoaded(Scene scene)
135 {
136 }
137
138 public void PostInitialise()
139 {
140 }
141
142 public void Close()
143 {
144 if (!m_Enabled)
145 return;
146
147// m_log.Debug("[GROUPS]: Shutting down group module.");
148
149 lock (m_ClientMap)
150 {
151 m_ClientMap.Clear();
152 }
153
154 lock (m_GroupMap)
155 {
156 m_GroupMap.Clear();
157 }
158 }
159
160 public string Name
161 {
162 get { return "GroupsModule"; }
163 }
164
165 public Type ReplaceableInterface
166 {
167 get { return null; }
168 }
169
170 #endregion
171
172 private void OnNewClient(IClientAPI client)
173 {
174 // Subscribe to instant messages
175// client.OnInstantMessage += OnInstantMessage;
176 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
177 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
178 lock (m_ClientMap)
179 {
180 if (!m_ClientMap.ContainsKey(client.AgentId))
181 {
182 m_ClientMap.Add(client.AgentId, client);
183 }
184 }
185
186 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
187 updateGroups[0] = osGroup;
188
189 client.SendGroupMembership(updateGroups);
190 }
191
192 private void OnAgentDataUpdateRequest(IClientAPI remoteClient,
193 UUID AgentID, UUID SessionID)
194 {
195 UUID ActiveGroupID;
196 string ActiveGroupName;
197 ulong ActiveGroupPowers;
198
199 string firstname = remoteClient.FirstName;
200 string lastname = remoteClient.LastName;
201
202 string ActiveGroupTitle = "I IZ N0T";
203
204 ActiveGroupID = osGroup.GroupID;
205 ActiveGroupName = osGroup.GroupName;
206 ActiveGroupPowers = osGroup.GroupPowers;
207
208 remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname,
209 lastname, ActiveGroupPowers, ActiveGroupName,
210 ActiveGroupTitle);
211 }
212
213// private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
214// {
215// }
216
217// private void OnGridInstantMessage(GridInstantMessage msg)
218// {
219// // Trigger the above event handler
220// OnInstantMessage(null, msg);
221// }
222
223 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client)
224 {
225 string groupnamereply = "Unknown";
226 UUID groupUUID = UUID.Zero;
227
228 lock (m_GroupMap)
229 {
230 if (m_GroupMap.ContainsKey(id))
231 {
232 GroupMembershipData grp = m_GroupMap[id];
233 groupnamereply = grp.GroupName;
234 groupUUID = grp.GroupID;
235 }
236 }
237 remote_client.SendGroupNameReply(groupUUID, groupnamereply);
238 }
239
240 private void OnClientClosed(UUID agentID, Scene scene)
241 {
242 lock (m_ClientMap)
243 {
244 if (m_ClientMap.ContainsKey(agentID))
245 {
246// IClientAPI cli = m_ClientMap[agentID];
247// if (cli != null)
248// {
249// //m_log.Info("[GROUPS]: Removing all reference to groups for " + cli.Name);
250// }
251// else
252// {
253// //m_log.Info("[GROUPS]: Removing all reference to groups for " + agentID.ToString());
254// }
255 m_ClientMap.Remove(agentID);
256 }
257 }
258 }
259 }
260}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..55e30a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers;
30using log4net; 31using log4net;
31using Mono.Addins; 32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
@@ -44,6 +45,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
44 private static readonly ILog m_log = LogManager.GetLogger( 45 private static readonly ILog m_log = LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
46 47
48 private Timer m_logTimer = new Timer(10000);
49 private List<GridInstantMessage> m_logData = new List<GridInstantMessage>();
50 private string m_restUrl;
51
47 /// <value> 52 /// <value>
48 /// Is this module enabled? 53 /// Is this module enabled?
49 /// </value> 54 /// </value>
@@ -63,9 +68,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
63 "InstantMessageModule", "InstantMessageModule") != 68 "InstantMessageModule", "InstantMessageModule") !=
64 "InstantMessageModule") 69 "InstantMessageModule")
65 return; 70 return;
71 m_restUrl = config.Configs["Messaging"].GetString("LogURL", String.Empty);
66 } 72 }
67 73
68 m_enabled = true; 74 m_enabled = true;
75 m_logTimer.AutoReset = false;
76 m_logTimer.Elapsed += LogTimerElapsed;
69 } 77 }
70 78
71 public void AddRegion(Scene scene) 79 public void AddRegion(Scene scene)
@@ -150,6 +158,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
150 { 158 {
151 byte dialog = im.dialog; 159 byte dialog = im.dialog;
152 160
161 if (client != null && dialog == (byte)InstantMessageDialog.MessageFromAgent)
162 LogInstantMesssage(im);
163
153 if (dialog != (byte)InstantMessageDialog.MessageFromAgent 164 if (dialog != (byte)InstantMessageDialog.MessageFromAgent
154 && dialog != (byte)InstantMessageDialog.StartTyping 165 && dialog != (byte)InstantMessageDialog.StartTyping
155 && dialog != (byte)InstantMessageDialog.StopTyping 166 && dialog != (byte)InstantMessageDialog.StopTyping
@@ -159,6 +170,32 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 return; 170 return;
160 } 171 }
161 172
173 //DateTime dt = DateTime.UtcNow;
174
175 // Ticks from UtcNow, but make it look like local. Evil, huh?
176 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
177
178 //try
179 //{
180 // // Convert that to the PST timezone
181 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
182 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
183 //}
184 //catch
185 //{
186 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
187 //}
188
189 //// And make it look local again to fool the unix time util
190 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
191
192 // If client is null, this message comes from storage and IS offline
193 if (client != null)
194 im.offline = 0;
195
196 if (im.offline == 0)
197 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
198
162 if (m_TransferModule != null) 199 if (m_TransferModule != null)
163 { 200 {
164 if (client != null) 201 if (client != null)
@@ -202,5 +239,35 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
202 // 239 //
203 OnInstantMessage(null, msg); 240 OnInstantMessage(null, msg);
204 } 241 }
242
243 private void LogInstantMesssage(GridInstantMessage im)
244 {
245 if (m_logData.Count < 20)
246 {
247 // Restart the log write timer
248 m_logTimer.Stop();
249 }
250 if (!m_logTimer.Enabled)
251 m_logTimer.Start();
252
253 lock (m_logData)
254 {
255 m_logData.Add(im);
256 }
257 }
258
259 private void LogTimerElapsed(object source, ElapsedEventArgs e)
260 {
261 lock (m_logData)
262 {
263 if (m_restUrl != String.Empty && m_logData.Count > 0)
264 {
265 bool success = SynchronousRestObjectRequester.MakeRequest<List<GridInstantMessage>, bool>("POST", m_restUrl + "/LogMessages/", m_logData);
266 if (!success)
267 m_log.ErrorFormat("[INSTANT MESSAGE]: Failed to save log data");
268 }
269 m_logData.Clear();
270 }
271 }
205 } 272 }
206} 273}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 40a400f..b321adb 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private bool m_Enabled = false; 52 private bool m_Enabled = false;
53 protected string m_MessageKey = String.Empty;
53 protected List<Scene> m_Scenes = new List<Scene>(); 54 protected List<Scene> m_Scenes = new List<Scene>();
54 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 55 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
55 56
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
69 public virtual void Initialise(IConfigSource config) 70 public virtual void Initialise(IConfigSource config)
70 { 71 {
71 IConfig cnf = config.Configs["Messaging"]; 72 IConfig cnf = config.Configs["Messaging"];
72 if (cnf != null && cnf.GetString( 73 if (cnf != null)
73 "MessageTransferModule", "MessageTransferModule") !=
74 "MessageTransferModule")
75 { 74 {
76 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 75 if (cnf.GetString("MessageTransferModule",
77 return; 76 "MessageTransferModule") != "MessageTransferModule")
78 } 77 {
78 return;
79 }
79 80
81 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82 }
83 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
80 m_Enabled = true; 84 m_Enabled = true;
81 } 85 }
82 86
@@ -135,6 +139,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
135 { 139 {
136 UUID toAgentID = new UUID(im.toAgentID); 140 UUID toAgentID = new UUID(im.toAgentID);
137 141
142 if (toAgentID == UUID.Zero)
143 return;
144
138 // Try root avatar only first 145 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 146 foreach (Scene scene in m_Scenes)
140 { 147 {
@@ -249,6 +256,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 256 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 257 && requestData.ContainsKey("binary_bucket"))
251 { 258 {
259 if (m_MessageKey != String.Empty)
260 {
261 XmlRpcResponse error_resp = new XmlRpcResponse();
262 Hashtable error_respdata = new Hashtable();
263 error_respdata["success"] = "FALSE";
264 error_resp.Value = error_respdata;
265
266 if (!requestData.Contains("message_key"))
267 return error_resp;
268 if (m_MessageKey != (string)requestData["message_key"])
269 return error_resp;
270 }
271
252 // Do the easy way of validating the UUIDs 272 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 273 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 274 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -425,24 +445,37 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 445 return resp;
426 } 446 }
427 447
428 /// <summary> 448 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
429 /// delegate for sending a grid instant message asynchronously
430 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID);
432 449
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 450 private class GIM {
434 { 451 public GridInstantMessage im;
435 GridInstantMessageDelegate icon = 452 public MessageResultNotification result;
436 (GridInstantMessageDelegate)iar.AsyncState; 453 };
437 icon.EndInvoke(iar);
438 }
439 454
455 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
456 private int numInstantMessageThreads = 0;
440 457
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 458 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
442 { 459 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 460 lock (pendingInstantMessages) {
461 if (numInstantMessageThreads >= 4) {
462 GIM gim = new GIM();
463 gim.im = im;
464 gim.result = result;
465 pendingInstantMessages.Enqueue(gim);
466 } else {
467 ++ numInstantMessageThreads;
468 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
469 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
470 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
471 }
472 }
473 }
444 474
445 d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); 475 private void GridInstantMessageCompleted(IAsyncResult iar)
476 {
477 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
478 d.EndInvoke(iar);
446 } 479 }
447 480
448 /// <summary> 481 /// <summary>
@@ -457,8 +490,31 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
457 /// Pass in 0 the first time this method is called. It will be called recursively with the last 490 /// Pass in 0 the first time this method is called. It will be called recursively with the last
458 /// regionhandle tried 491 /// regionhandle tried
459 /// </param> 492 /// </param>
460 protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) 493 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
461 { 494 {
495 GIM gim;
496 do {
497 try {
498 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
499 } catch (Exception e) {
500 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
501 }
502 lock (pendingInstantMessages) {
503 if (pendingInstantMessages.Count > 0) {
504 gim = pendingInstantMessages.Dequeue();
505 im = gim.im;
506 result = gim.result;
507 } else {
508 gim = null;
509 -- numInstantMessageThreads;
510 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
511 }
512 }
513 } while (gim != null);
514 }
515 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
516 {
517
462 UUID toAgentID = new UUID(im.toAgentID); 518 UUID toAgentID = new UUID(im.toAgentID);
463 519
464 PresenceInfo upd = null; 520 PresenceInfo upd = null;
@@ -525,7 +581,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
525 581
526 if (upd != null) 582 if (upd != null)
527 { 583 {
528 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, 584 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
529 upd.RegionID); 585 upd.RegionID);
530 if (reginfo != null) 586 if (reginfo != null)
531 { 587 {
@@ -674,6 +730,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
674 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
675 gim["region_id"] = new UUID(msg.RegionID).ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
676 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)
734 gim["message_key"] = m_MessageKey;
677 return gim; 735 return gim;
678 } 736 }
679 737
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 7f3d0a2..2d46276 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -173,7 +173,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
173 173
174 private void RetrieveInstantMessages(IClientAPI client) 174 private void RetrieveInstantMessages(IClientAPI client)
175 { 175 {
176 if (m_RestURL != "") 176 if (m_RestURL == String.Empty)
177 {
178 return;
179 }
180 else
177 { 181 {
178 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 182 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
179 183
@@ -181,28 +185,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
181 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 185 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
182 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 186 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
183 187
184 if (msglist == null) 188 if (msglist != null)
185 { 189 {
186 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); 190 foreach (GridInstantMessage im in msglist)
187 return;
188 }
189
190 foreach (GridInstantMessage im in msglist)
191 {
192 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
193 // send it directly or else the item will be given twice
194 client.SendInstantMessage(im);
195 else
196 { 191 {
197 // Send through scene event manager so all modules get a chance 192 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
198 // to look at this message before it gets delivered. 193 // send it directly or else the item will be given twice
199 // 194 client.SendInstantMessage(im);
200 // Needed for proper state management for stored group 195 else
201 // invitations 196 {
202 // 197 // Send through scene event manager so all modules get a chance
203 Scene s = FindScene(client.AgentId); 198 // to look at this message before it gets delivered.
204 if (s != null) 199 //
205 s.EventManager.TriggerIncomingInstantMessage(im); 200 // Needed for proper state management for stored group
201 // invitations
202 //
203
204 im.offline = 1;
205
206 Scene s = FindScene(client.AgentId);
207 if (s != null)
208 s.EventManager.TriggerIncomingInstantMessage(im);
209 }
206 } 210 }
207 } 211 }
208 } 212 }
@@ -214,24 +218,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
214 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 218 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
215 im.dialog != (byte)InstantMessageDialog.GroupNotice && 219 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
216 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 220 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
217 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 221 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
222 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
218 { 223 {
219 return; 224 return;
220 } 225 }
221 226
222 if (!m_ForwardOfflineGroupMessages)
223 {
224 if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
225 im.dialog == (byte)InstantMessageDialog.GroupInvitation)
226 return;
227 }
228
229 Scene scene = FindScene(new UUID(im.fromAgentID)); 227 Scene scene = FindScene(new UUID(im.fromAgentID));
230 if (scene == null) 228 if (scene == null)
231 scene = m_SceneList[0]; 229 scene = m_SceneList[0];
232 230
233 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 231 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
234 "POST", m_RestURL+"/SaveMessage/", im); 232 "POST", m_RestURL+"/SaveMessage/?scope=" +
233 scene.RegionInfo.ScopeID.ToString(), im);
235 234
236 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 235 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
237 { 236 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 31c42d8..d56e469 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -656,4 +656,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
656 m_assetsLoaded = true; 656 m_assetsLoaded = true;
657 } 657 }
658 } 658 }
659} \ No newline at end of file 659}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 797097f..cef6177 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -519,6 +519,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
519 return null; 519 return null;
520 } 520 }
521 521
522 return account;
523 /*
522 try 524 try
523 { 525 {
524 string encpass = Util.Md5Hash(pass); 526 string encpass = Util.Md5Hash(pass);
@@ -539,6 +541,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
539 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); 541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message);
540 return null; 542 return null;
541 } 543 }
544 */
542 } 545 }
543 546
544 /// <summary> 547 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 1417a19..e285f21 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -164,8 +164,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
164 if (im.binaryBucket.Length < 17) // Invalid 164 if (im.binaryBucket.Length < 17) // Invalid
165 return; 165 return;
166 166
167 UUID receipientID = new UUID(im.toAgentID); 167 UUID recipientID = new UUID(im.toAgentID);
168 ScenePresence user = scene.GetScenePresence(receipientID); 168 ScenePresence user = scene.GetScenePresence(recipientID);
169 UUID copyID; 169 UUID copyID;
170 170
171 // First byte is the asset type 171 // First byte is the asset type
@@ -180,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
180 folderID, new UUID(im.toAgentID)); 180 folderID, new UUID(im.toAgentID));
181 181
182 InventoryFolderBase folderCopy 182 InventoryFolderBase folderCopy
183 = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); 183 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
184 184
185 if (folderCopy == null) 185 if (folderCopy == null)
186 { 186 {
@@ -239,6 +239,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
239 im.imSessionID = copyID.Guid; 239 im.imSessionID = copyID.Guid;
240 } 240 }
241 241
242 im.offline = 0;
243
242 // Send the IM to the recipient. The item is already 244 // Send the IM to the recipient. The item is already
243 // in their inventory, so it will not be lost if 245 // in their inventory, so it will not be lost if
244 // they are offline. 246 // they are offline.
@@ -258,8 +260,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
258 }); 260 });
259 } 261 }
260 } 262 }
261 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) 263 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
264 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
262 { 265 {
266 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
267 IInventoryService invService = scene.InventoryService;
268
269 // Special case: folder redirect.
270 // RLV uses this
271 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
272 {
273 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, client.AgentId);
274 folder = invService.GetFolder(folder);
275
276 if (folder != null)
277 {
278 if (im.binaryBucket.Length >= 16)
279 {
280 UUID destFolderID = new UUID(im.binaryBucket, 0);
281 if (destFolderID != UUID.Zero)
282 {
283 InventoryFolderBase destFolder = new InventoryFolderBase(destFolderID, client.AgentId);
284 destFolder = invService.GetFolder(destFolder);
285 if (destFolder != null)
286 {
287 if (folder.ParentID != destFolder.ID)
288 {
289 folder.ParentID = destFolder.ID;
290 invService.MoveFolder(folder);
291 client.SendBulkUpdateInventory(folder);
292 }
293 }
294 }
295 }
296 }
297 }
298
263 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 299 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
264 300
265 if (user != null) // Local 301 if (user != null) // Local
@@ -269,27 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
269 else 305 else
270 { 306 {
271 if (m_TransferModule != null) 307 if (m_TransferModule != null)
272 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 308 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
273
274 // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
275 // and is apparently supposed to fix bulk inventory updates after accepting items. But
276 // instead it appears to cause two copies of an accepted folder for the receiving user in
277 // at least some cases. Folder/item update is already done when the offer is made (see code above)
278
279// // Send BulkUpdateInventory
280// IInventoryService invService = scene.InventoryService;
281// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
282//
283// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
284// folder = invService.GetFolder(folder);
285//
286// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
287//
288// // If the user has left the scene by the time the message comes back then we can't send
289// // them the update.
290// if (fromUser != null)
291// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
292 });
293 } 309 }
294 } 310 }
295 311
@@ -402,6 +418,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
402 previousParentFolderID = folder.ParentID; 418 previousParentFolderID = folder.ParentID;
403 folder.ParentID = trashFolder.ID; 419 folder.ParentID = trashFolder.ID;
404 invService.MoveFolder(folder); 420 invService.MoveFolder(folder);
421 client.SendBulkUpdateInventory(folder);
405 } 422 }
406 } 423 }
407 424
@@ -451,22 +468,113 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
451 /// 468 ///
452 /// </summary> 469 /// </summary>
453 /// <param name="msg"></param> 470 /// <param name="msg"></param>
454 private void OnGridInstantMessage(GridInstantMessage msg) 471 private void OnGridInstantMessage(GridInstantMessage im)
455 { 472 {
456 // Check if this is ours to handle 473 // Check if this is ours to handle
457 // 474 //
458 Scene scene = FindClientScene(new UUID(msg.toAgentID)); 475 Scene scene = FindClientScene(new UUID(im.toAgentID));
459 476
460 if (scene == null) 477 if (scene == null)
461 return; 478 return;
462 479
463 // Find agent to deliver to 480 // Find agent to deliver to
464 // 481 //
465 ScenePresence user = scene.GetScenePresence(new UUID(msg.toAgentID)); 482 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
483 if (user == null)
484 return;
485
486 // This requires a little bit of processing because we have to make the
487 // new item visible in the recipient's inventory here
488 //
489 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
490 {
491 if (im.binaryBucket.Length < 17) // Invalid
492 return;
493
494 UUID recipientID = new UUID(im.toAgentID);
495
496 // First byte is the asset type
497 AssetType assetType = (AssetType)im.binaryBucket[0];
498
499 if (AssetType.Folder == assetType)
500 {
501 UUID folderID = new UUID(im.binaryBucket, 1);
502
503 InventoryFolderBase given =
504 new InventoryFolderBase(folderID, recipientID);
505 InventoryFolderBase folder =
506 scene.InventoryService.GetFolder(given);
507
508 if (folder != null)
509 user.ControllingClient.SendBulkUpdateInventory(folder);
510 }
511 else
512 {
513 UUID itemID = new UUID(im.binaryBucket, 1);
466 514
467 // Just forward to local handling 515 InventoryItemBase given =
468 OnInstantMessage(user.ControllingClient, msg); 516 new InventoryItemBase(itemID, recipientID);
517 InventoryItemBase item =
518 scene.InventoryService.GetItem(given);
519
520 if (item != null)
521 {
522 user.ControllingClient.SendBulkUpdateInventory(item);
523 }
524 }
525 user.ControllingClient.SendInstantMessage(im);
526 }
527 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
528 {
529 if (im.binaryBucket.Length < 1) // Invalid
530 return;
531
532 UUID recipientID = new UUID(im.toAgentID);
469 533
534 // Bucket is the asset type
535 AssetType assetType = (AssetType)im.binaryBucket[0];
536
537 if (AssetType.Folder == assetType)
538 {
539 UUID folderID = new UUID(im.imSessionID);
540
541 InventoryFolderBase given =
542 new InventoryFolderBase(folderID, recipientID);
543 InventoryFolderBase folder =
544 scene.InventoryService.GetFolder(given);
545
546 if (folder != null)
547 user.ControllingClient.SendBulkUpdateInventory(folder);
548 }
549 else
550 {
551 UUID itemID = new UUID(im.imSessionID);
552
553 InventoryItemBase given =
554 new InventoryItemBase(itemID, recipientID);
555 InventoryItemBase item =
556 scene.InventoryService.GetItem(given);
557
558 if (item != null)
559 {
560 user.ControllingClient.SendBulkUpdateInventory(item);
561 }
562 }
563
564 // Fix up binary bucket since this may be 17 chars long here
565 Byte[] bucket = new Byte[1];
566 bucket[0] = im.binaryBucket[0];
567 im.binaryBucket = bucket;
568
569 user.ControllingClient.SendInstantMessage(im);
570 }
571 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
572 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
573 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
574 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
575 {
576 user.ControllingClient.SendInstantMessage(im);
577 }
470 } 578 }
471 } 579 }
472} 580}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 7f4606b..0c64f19 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -163,16 +163,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
163 scene.RegionInfo.RegionHandle, 163 scene.RegionInfo.RegionHandle,
164 (uint)presence.AbsolutePosition.X, 164 (uint)presence.AbsolutePosition.X,
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)Math.Ceiling(presence.AbsolutePosition.Z)); 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("TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, 170 GridInstantMessage m;
171 client.FirstName+" "+client.LastName, targetid, 171
172 (byte)InstantMessageDialog.RequestTeleport, false, 172 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.GodLevel >= 200 && (!scene.Permissions.IsAdministrator(targetid)))
173 message, dest, false, presence.AbsolutePosition, 173 {
174 new Byte[0], true); 174 m = new GridInstantMessage(scene, client.AgentId,
175 175 client.FirstName+" "+client.LastName, targetid,
176 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
177 message, dest, false, presence.AbsolutePosition,
178 new Byte[0], true);
179 }
180 else
181 {
182 m = new GridInstantMessage(scene, client.AgentId,
183 client.FirstName+" "+client.LastName, targetid,
184 (byte)InstantMessageDialog.RequestTeleport, false,
185 message, dest, false, presence.AbsolutePosition,
186 new Byte[0], true);
187 }
188
176 if (m_TransferModule != null) 189 if (m_TransferModule != null)
177 { 190 {
178 m_TransferModule.SendInstantMessage(m, 191 m_TransferModule.SendInstantMessage(m,
@@ -207,7 +220,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
207 { 220 {
208 // Forward remote teleport requests 221 // Forward remote teleport requests
209 // 222 //
210 if (msg.dialog != 22) 223 if (msg.dialog != (byte)InstantMessageDialog.RequestTeleport &&
224 msg.dialog != (byte)InstantMessageDialog.GodLikeRequestTeleport)
211 return; 225 return;
212 226
213 if (m_TransferModule != null) 227 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 6545a99..de8925d 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework
57 /// <summary> 57 /// <summary>
58 /// Each agent has its own capabilities handler. 58 /// Each agent has its own capabilities handler.
59 /// </summary> 59 /// </summary>
60 protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>(); 60 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
61 61
62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>(); 62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>();
63 63
@@ -118,9 +118,10 @@ namespace OpenSim.Region.CoreModules.Framework
118 get { return null; } 118 get { return null; }
119 } 119 }
120 120
121 public void CreateCaps(UUID agentId) 121 public void CreateCaps(UUID agentId, uint circuitCode)
122 { 122 {
123 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId)) 123 int flags = m_scene.GetUserFlags(agentId);
124 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
124 return; 125 return;
125 126
126 Caps caps; 127 Caps caps;
@@ -128,9 +129,9 @@ namespace OpenSim.Region.CoreModules.Framework
128 129
129 lock (m_capsObjects) 130 lock (m_capsObjects)
130 { 131 {
131 if (m_capsObjects.ContainsKey(agentId)) 132 if (m_capsObjects.ContainsKey(circuitCode))
132 { 133 {
133 Caps oldCaps = m_capsObjects[agentId]; 134 Caps oldCaps = m_capsObjects[circuitCode];
134 135
135 //m_log.WarnFormat( 136 //m_log.WarnFormat(
136 // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ", 137 // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ",
@@ -141,13 +142,12 @@ namespace OpenSim.Region.CoreModules.Framework
141 (MainServer.Instance == null) ? 0: MainServer.Instance.Port, 142 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
142 capsObjectPath, agentId, m_scene.RegionInfo.RegionName); 143 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
143 144
144 m_capsObjects[agentId] = caps; 145 m_capsObjects[circuitCode] = caps;
145 } 146 }
146
147 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 147 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
148 } 148 }
149 149
150 public void RemoveCaps(UUID agentId) 150 public void RemoveCaps(UUID agentId, uint circuitCode)
151 { 151 {
152 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName); 152 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName);
153 lock (m_childrenSeeds) 153 lock (m_childrenSeeds)
@@ -160,11 +160,11 @@ namespace OpenSim.Region.CoreModules.Framework
160 160
161 lock (m_capsObjects) 161 lock (m_capsObjects)
162 { 162 {
163 if (m_capsObjects.ContainsKey(agentId)) 163 if (m_capsObjects.ContainsKey(circuitCode))
164 { 164 {
165 m_capsObjects[agentId].DeregisterHandlers(); 165 m_capsObjects[circuitCode].DeregisterHandlers();
166 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); 166 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]);
167 m_capsObjects.Remove(agentId); 167 m_capsObjects.Remove(circuitCode);
168 } 168 }
169 else 169 else
170 { 170 {
@@ -175,19 +175,30 @@ namespace OpenSim.Region.CoreModules.Framework
175 } 175 }
176 } 176 }
177 177
178 public Caps GetCapsForUser(UUID agentId) 178 public Caps GetCapsForUser(uint circuitCode)
179 { 179 {
180 lock (m_capsObjects) 180 lock (m_capsObjects)
181 { 181 {
182 if (m_capsObjects.ContainsKey(agentId)) 182 if (m_capsObjects.ContainsKey(circuitCode))
183 { 183 {
184 return m_capsObjects[agentId]; 184 return m_capsObjects[circuitCode];
185 } 185 }
186 } 186 }
187 187
188 return null; 188 return null;
189 } 189 }
190 190
191 public void ActivateCaps(uint circuitCode)
192 {
193 lock (m_capsObjects)
194 {
195 if (m_capsObjects.ContainsKey(circuitCode))
196 {
197 m_capsObjects[circuitCode].Activate();
198 }
199 }
200 }
201
191 public void SetAgentCapsSeeds(AgentCircuitData agent) 202 public void SetAgentCapsSeeds(AgentCircuitData agent)
192 { 203 {
193 lock (m_capsPaths) 204 lock (m_capsPaths)
@@ -287,9 +298,9 @@ namespace OpenSim.Region.CoreModules.Framework
287 298
288 lock (m_capsObjects) 299 lock (m_capsObjects)
289 { 300 {
290 foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) 301 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
291 { 302 {
292 capsReport.AppendFormat("** User {0}:\n", kvp.Key); 303 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
293 Caps caps = kvp.Value; 304 Caps caps = kvp.Value;
294 305
295 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 306 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
@@ -337,6 +348,7 @@ namespace OpenSim.Region.CoreModules.Framework
337 348
338 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName) 349 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName)
339 { 350 {
351 /*
340 sb.AppendFormat("Capability name {0}\n", capName); 352 sb.AppendFormat("Capability name {0}\n", capName);
341 353
342 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 354 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -382,10 +394,12 @@ namespace OpenSim.Region.CoreModules.Framework
382 } 394 }
383 395
384 sb.Append(cdt.ToString()); 396 sb.Append(cdt.ToString());
397 */
385 } 398 }
386 399
387 private void BuildSummaryStatsByCapReport(StringBuilder sb) 400 private void BuildSummaryStatsByCapReport(StringBuilder sb)
388 { 401 {
402 /*
389 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 403 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
390 cdt.AddColumn("Name", 34); 404 cdt.AddColumn("Name", 34);
391 cdt.AddColumn("Req Received", 12); 405 cdt.AddColumn("Req Received", 12);
@@ -442,10 +456,12 @@ namespace OpenSim.Region.CoreModules.Framework
442 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); 456 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
443 457
444 sb.Append(cdt.ToString()); 458 sb.Append(cdt.ToString());
459 */
445 } 460 }
446 461
447 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams) 462 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams)
448 { 463 {
464 /*
449 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) 465 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
450 return; 466 return;
451 467
@@ -476,10 +492,12 @@ namespace OpenSim.Region.CoreModules.Framework
476 } 492 }
477 493
478 MainConsole.Instance.Output(sb.ToString()); 494 MainConsole.Instance.Output(sb.ToString());
495 */
479 } 496 }
480 497
481 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp) 498 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp)
482 { 499 {
500 /*
483 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root"); 501 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root");
484 502
485 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 503 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -505,10 +523,12 @@ namespace OpenSim.Region.CoreModules.Framework
505 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled); 523 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
506 524
507 sb.Append(cdt.ToString()); 525 sb.Append(cdt.ToString());
526 */
508 } 527 }
509 528
510 private void BuildSummaryStatsByUserReport(StringBuilder sb) 529 private void BuildSummaryStatsByUserReport(StringBuilder sb)
511 { 530 {
531 /*
512 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 532 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
513 cdt.AddColumn("Name", 32); 533 cdt.AddColumn("Name", 32);
514 cdt.AddColumn("Type", 5); 534 cdt.AddColumn("Type", 5);
@@ -548,6 +568,7 @@ namespace OpenSim.Region.CoreModules.Framework
548 ); 568 );
549 569
550 sb.Append(cdt.ToString()); 570 sb.Append(cdt.ToString());
571 */
551 } 572 }
552 573
553 private class CapTableRow 574 private class CapTableRow
@@ -564,4 +585,4 @@ namespace OpenSim.Region.CoreModules.Framework
564 } 585 }
565 } 586 }
566 } 587 }
567} \ No newline at end of file 588}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 87f0264..711167f 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -368,7 +368,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
368 /// <param name="sp"></param> 368 /// <param name="sp"></param>
369 /// <param name="position"></param> 369 /// <param name="position"></param>
370 /// <param name="lookAt"></param> 370 /// <param name="lookAt"></param>
371 /// <param name="teleportFlags"></param 371 /// <param name="teleportFlags"></param>
372 private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags) 372 private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags)
373 { 373 {
374 m_log.DebugFormat( 374 m_log.DebugFormat(
@@ -403,11 +403,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
403 position.Z = newPosZ; 403 position.Z = newPosZ;
404 } 404 }
405 405
406 if (sp.Flying)
407 teleportFlags |= (uint)TeleportFlags.IsFlying;
408
406 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 409 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
407 410
408 sp.ControllingClient.SendTeleportStart(teleportFlags); 411 sp.ControllingClient.SendTeleportStart(teleportFlags);
409 412
410 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 413 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
414 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags;
411 sp.Velocity = Vector3.Zero; 415 sp.Velocity = Vector3.Zero;
412 sp.Teleport(position); 416 sp.Teleport(position);
413 417
@@ -608,8 +612,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
608 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, 612 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
609 // it's actually doing a lot of work. 613 // it's actually doing a lot of work.
610 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 614 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
611 615 if (endPoint == null || endPoint.Address == null)
612 if (endPoint.Address == null)
613 { 616 {
614 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); 617 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
615 618
@@ -646,6 +649,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
646 // both regions 649 // both regions
647 if (sp.ParentID != (uint)0) 650 if (sp.ParentID != (uint)0)
648 sp.StandUp(); 651 sp.StandUp();
652 else if (sp.Flying)
653 teleportFlags |= (uint)TeleportFlags.IsFlying;
649 654
650 if (DisableInterRegionTeleportCancellation) 655 if (DisableInterRegionTeleportCancellation)
651 teleportFlags |= (uint)TeleportFlags.DisableCancel; 656 teleportFlags |= (uint)TeleportFlags.DisableCancel;
@@ -1263,11 +1268,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1263 1268
1264 #region Teleport Home 1269 #region Teleport Home
1265 1270
1266 public virtual void TriggerTeleportHome(UUID id, IClientAPI client) 1271 public virtual void TriggerTeleportHome(UUID id, IClientAPI client)
1267 { 1272 {
1268 TeleportHome(id, client); 1273 TeleportHome(id, client);
1269 } 1274 }
1270 1275
1271 public virtual bool TeleportHome(UUID id, IClientAPI client) 1276 public virtual bool TeleportHome(UUID id, IClientAPI client)
1272 { 1277 {
1273 m_log.DebugFormat( 1278 m_log.DebugFormat(
@@ -1278,6 +1283,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1278 1283
1279 if (uinfo != null) 1284 if (uinfo != null)
1280 { 1285 {
1286 if (uinfo.HomeRegionID == UUID.Zero)
1287 {
1288 // can't find the Home region: Tell viewer and abort
1289 client.SendTeleportFailed("You don't have a home position set.");
1290 return false;
1291 }
1281 GridRegion regionInfo = Scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); 1292 GridRegion regionInfo = Scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
1282 if (regionInfo == null) 1293 if (regionInfo == null)
1283 { 1294 {
@@ -1297,9 +1308,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1297 } 1308 }
1298 else 1309 else
1299 { 1310 {
1300 m_log.ErrorFormat( 1311 // can't find the Home region: Tell viewer and abort
1301 "[ENTITY TRANSFER MODULE]: No grid user information found for {0} {1}. Cannot send home.", 1312 client.SendTeleportFailed("Your home region could not be found.");
1302 client.Name, client.AgentId);
1303 } 1313 }
1304 return false; 1314 return false;
1305 } 1315 }
@@ -1309,15 +1319,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1309 1319
1310 #region Agent Crossings 1320 #region Agent Crossings
1311 1321
1312 public bool Cross(ScenePresence agent, bool isFlying) 1322 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
1313 { 1323 {
1314 Scene scene = agent.Scene; 1324 version = String.Empty;
1315 Vector3 pos = agent.AbsolutePosition; 1325 newpos = new Vector3(pos.X, pos.Y, pos.Z);
1316 1326
1317// m_log.DebugFormat( 1327// m_log.DebugFormat(
1318// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1328// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1319 1329
1320 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
1321 uint neighbourx = scene.RegionInfo.RegionLocX; 1330 uint neighbourx = scene.RegionInfo.RegionLocX;
1322 uint neighboury = scene.RegionInfo.RegionLocY; 1331 uint neighboury = scene.RegionInfo.RegionLocY;
1323 const float boundaryDistance = 1.7f; 1332 const float boundaryDistance = 1.7f;
@@ -1338,52 +1347,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1338 } 1347 }
1339 else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) 1348 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1340 { 1349 {
1341 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); 1350 neighboury--;
1342 if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0) 1351 newpos.Y = Constants.RegionSize - enterDistance;
1343 {
1344 neighboury--;
1345 newpos.Y = Constants.RegionSize - enterDistance;
1346 }
1347 else
1348 {
1349 agent.IsInTransit = true;
1350
1351 neighboury = b.TriggerRegionY;
1352 neighbourx = b.TriggerRegionX;
1353
1354 Vector3 newposition = pos;
1355 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
1356 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
1357 agent.ControllingClient.SendAgentAlertMessage(
1358 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
1359 InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
1360 return true;
1361 }
1362 }
1363
1364 Border ba = scene.GetCrossedBorder(pos + westCross, Cardinals.W);
1365 if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0)
1366 {
1367 neighbourx--;
1368 newpos.X = Constants.RegionSize - enterDistance;
1369 }
1370 else
1371 {
1372 agent.IsInTransit = true;
1373
1374 neighboury = ba.TriggerRegionY;
1375 neighbourx = ba.TriggerRegionX;
1376
1377 Vector3 newposition = pos;
1378 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
1379 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
1380 agent.ControllingClient.SendAgentAlertMessage(
1381 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
1382 InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
1383
1384 return true;
1385 } 1352 }
1386 1353
1354 neighbourx--;
1355 newpos.X = Constants.RegionSize - enterDistance;
1387 } 1356 }
1388 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E)) 1357 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
1389 { 1358 {
@@ -1393,26 +1362,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1393 1362
1394 if (scene.TestBorderCross(pos + southCross, Cardinals.S)) 1363 if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1395 { 1364 {
1396 Border ba = scene.GetCrossedBorder(pos + southCross, Cardinals.S); 1365 neighboury--;
1397 if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0) 1366 newpos.Y = Constants.RegionSize - enterDistance;
1398 {
1399 neighboury--;
1400 newpos.Y = Constants.RegionSize - enterDistance;
1401 }
1402 else
1403 {
1404 agent.IsInTransit = true;
1405
1406 neighboury = ba.TriggerRegionY;
1407 neighbourx = ba.TriggerRegionX;
1408 Vector3 newposition = pos;
1409 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
1410 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
1411 agent.ControllingClient.SendAgentAlertMessage(
1412 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
1413 InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
1414 return true;
1415 }
1416 } 1367 }
1417 else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1368 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
1418 { 1369 {
@@ -1424,25 +1375,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1424 else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) 1375 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1425 { 1376 {
1426 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); 1377 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
1427 if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0) 1378 neighboury--;
1428 { 1379 newpos.Y = Constants.RegionSize - enterDistance;
1429 neighboury--;
1430 newpos.Y = Constants.RegionSize - enterDistance;
1431 }
1432 else
1433 {
1434 agent.IsInTransit = true;
1435
1436 neighboury = b.TriggerRegionY;
1437 neighbourx = b.TriggerRegionX;
1438 Vector3 newposition = pos;
1439 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
1440 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
1441 agent.ControllingClient.SendAgentAlertMessage(
1442 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
1443 InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
1444 return true;
1445 }
1446 } 1380 }
1447 else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1381 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
1448 { 1382 {
@@ -1476,19 +1410,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1476 } 1410 }
1477 */ 1411 */
1478 1412
1479 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); 1413 xDest = neighbourx;
1414 yDest = neighboury;
1480 1415
1481 int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); 1416 int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
1482 1417
1418 ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y);
1419
1483 ExpiringCache<ulong, DateTime> r; 1420 ExpiringCache<ulong, DateTime> r;
1484 DateTime banUntil; 1421 DateTime banUntil;
1485 1422
1486 if (m_bannedRegions.TryGetValue(agent.ControllingClient.AgentId, out r)) 1423 if (m_bannedRegions.TryGetValue(agentID, out r))
1487 { 1424 {
1488 if (r.TryGetValue(neighbourHandle, out banUntil)) 1425 if (r.TryGetValue(neighbourHandle, out banUntil))
1489 { 1426 {
1490 if (DateTime.Now < banUntil) 1427 if (DateTime.Now < banUntil)
1491 return false; 1428 return null;
1492 r.Remove(neighbourHandle); 1429 r.Remove(neighbourHandle);
1493 } 1430 }
1494 } 1431 }
@@ -1500,28 +1437,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1500 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); 1437 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
1501 1438
1502 string reason; 1439 string reason;
1503 string version; 1440 if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
1504 if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out version, out reason))
1505 { 1441 {
1506 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
1507 if (r == null) 1442 if (r == null)
1508 { 1443 {
1509 r = new ExpiringCache<ulong, DateTime>(); 1444 r = new ExpiringCache<ulong, DateTime>();
1510 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 1445 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
1511 1446
1512 m_bannedRegions.Add(agent.ControllingClient.AgentId, r, TimeSpan.FromSeconds(45)); 1447 m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45));
1513 } 1448 }
1514 else 1449 else
1515 { 1450 {
1516 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 1451 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
1517 } 1452 }
1453 return null;
1454 }
1455
1456 return neighbourRegion;
1457 }
1458
1459 public bool Cross(ScenePresence agent, bool isFlying)
1460 {
1461 uint x;
1462 uint y;
1463 Vector3 newpos;
1464 string version;
1465
1466 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos);
1467 if (neighbourRegion == null)
1468 {
1469 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
1518 return false; 1470 return false;
1519 } 1471 }
1520 1472
1521 agent.IsInTransit = true; 1473 agent.IsInTransit = true;
1522 1474
1523 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; 1475 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
1524 d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); 1476 d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d);
1525 1477
1526 return true; 1478 return true;
1527 } 1479 }
@@ -1603,52 +1555,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1603 icon.EndInvoke(iar); 1555 icon.EndInvoke(iar);
1604 } 1556 }
1605 1557
1606 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); 1558 public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion)
1559 {
1560 if (neighbourRegion == null)
1561 return false;
1562
1563 m_entityTransferStateMachine.SetInTransit(agent.UUID);
1564
1565 agent.RemoveFromPhysicalScene();
1566
1567 return true;
1568 }
1607 1569
1608 /// <summary> 1570 /// <summary>
1609 /// This Closes child agents on neighbouring regions 1571 /// This Closes child agents on neighbouring regions
1610 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1572 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1611 /// </summary> 1573 /// </summary>
1612 protected ScenePresence CrossAgentToNewRegionAsync( 1574 public ScenePresence CrossAgentToNewRegionAsync(
1613 ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, 1575 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1614 bool isFlying, string version) 1576 bool isFlying, string version)
1615 { 1577 {
1616 if (neighbourRegion == null) 1578 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
1579 {
1580 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1617 return agent; 1581 return agent;
1582 }
1618 1583
1619 if (!m_entityTransferStateMachine.SetInTransit(agent.UUID)) 1584 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying))
1620 { 1585 {
1621 m_log.ErrorFormat( 1586 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1622 "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2} - agent is already in transit",
1623 agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName);
1624 return agent; 1587 return agent;
1625 } 1588 }
1626 1589
1627 bool transitWasReset = false; 1590 CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version);
1591 return agent;
1592 }
1628 1593
1594 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying)
1595 {
1629 try 1596 try
1630 { 1597 {
1631 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); 1598 AgentData cAgent = new AgentData();
1632
1633 m_log.DebugFormat(
1634 "[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}",
1635 agent.Firstname, agent.Lastname, neighbourx, neighboury, version);
1636
1637 Scene m_scene = agent.Scene;
1638
1639 if (!agent.ValidateAttachments())
1640 m_log.DebugFormat(
1641 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
1642 agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
1643
1644 pos = pos + agent.Velocity;
1645 Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0);
1646
1647 agent.RemoveFromPhysicalScene();
1648
1649 AgentData cAgent = new AgentData();
1650 agent.CopyTo(cAgent); 1599 agent.CopyTo(cAgent);
1651 cAgent.Position = pos; 1600 cAgent.Position = pos + agent.Velocity;
1652 if (isFlying) 1601 if (isFlying)
1653 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; 1602 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1654 1603
@@ -1658,7 +1607,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1658 // Beyond this point, extra cleanup is needed beyond removing transit state 1607 // Beyond this point, extra cleanup is needed beyond removing transit state
1659 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); 1608 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
1660 1609
1661 if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) 1610 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent))
1662 { 1611 {
1663 // region doesn't take it 1612 // region doesn't take it
1664 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1613 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
@@ -1670,88 +1619,108 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1670 ReInstantiateScripts(agent); 1619 ReInstantiateScripts(agent);
1671 agent.AddToPhysicalScene(isFlying); 1620 agent.AddToPhysicalScene(isFlying);
1672 1621
1673 return agent; 1622 return false;
1674 } 1623 }
1675 1624
1676 //m_log.Debug("BEFORE CROSS"); 1625 }
1677 //Scene.DumpChildrenSeeds(UUID); 1626 catch (Exception e)
1678 //DumpKnownRegions(); 1627 {
1679 string agentcaps; 1628 m_log.ErrorFormat(
1680 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) 1629 "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}",
1681 { 1630 agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace);
1682 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
1683 neighbourRegion.RegionHandle);
1684 return agent;
1685 }
1686 1631
1687 // No turning back 1632 // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc.
1688 agent.IsChildAgent = true; 1633 return false;
1634 }
1689 1635
1690 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1636 return true;
1637 }
1691 1638
1692 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); 1639 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1640 bool isFlying, string version)
1641 {
1642 agent.ControllingClient.RequestClientInfo();
1693 1643
1694 if (m_eqModule != null) 1644 string agentcaps;
1695 { 1645 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
1696 m_eqModule.CrossRegion( 1646 {
1697 neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, 1647 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
1698 capsPath, agent.UUID, agent.ControllingClient.SessionId); 1648 neighbourRegion.RegionHandle);
1699 } 1649 return;
1700 else 1650 }
1701 {
1702 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
1703 capsPath);
1704 }
1705 1651
1706 // SUCCESS! 1652 // No turning back
1707 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); 1653 agent.IsChildAgent = true;
1708 1654
1709 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. 1655 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
1710 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1711 1656
1712 agent.MakeChildAgent(); 1657 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
1713 1658
1714 // FIXME: Possibly this should occur lower down after other commands to close other agents, 1659 Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0);
1715 // but not sure yet what the side effects would be. 1660
1716 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1661 if (m_eqModule != null)
1717 transitWasReset = true; 1662 {
1663 m_eqModule.CrossRegion(
1664 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint,
1665 capsPath, agent.UUID, agent.ControllingClient.SessionId);
1666 }
1667 else
1668 {
1669 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint,
1670 capsPath);
1671 }
1718 1672
1719 // now we have a child agent in this region. Request all interesting data about other (root) agents 1673 // SUCCESS!
1720 agent.SendOtherAgentsAvatarDataToMe(); 1674 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
1721 agent.SendOtherAgentsAppearanceToMe();
1722 1675
1723 // Backwards compatibility. Best effort 1676 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1724 if (version == "Unknown" || version == string.Empty) 1677 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1725 {
1726 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1727 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1728 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1729 }
1730 1678
1731 // Next, let's close the child agent connections that are too far away. 1679 agent.MakeChildAgent();
1732 agent.CloseChildAgents(neighbourx, neighboury);
1733 1680
1734 AgentHasMovedAway(agent, false); 1681 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1735 1682 // but not sure yet what the side effects would be.
1736 //m_log.Debug("AFTER CROSS"); 1683 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1737 //Scene.DumpChildrenSeeds(UUID);
1738 //DumpKnownRegions();
1739 }
1740 catch (Exception e)
1741 {
1742 m_log.ErrorFormat(
1743 "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}",
1744 agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace);
1745 1684
1746 // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. 1685 // now we have a child agent in this region. Request all interesting data about other (root) agents
1747 } 1686 agent.SendOtherAgentsAvatarDataToMe();
1748 finally 1687 agent.SendOtherAgentsAppearanceToMe();
1688
1689 // Backwards compatibility. Best effort
1690 if (version == "Unknown" || version == string.Empty)
1749 { 1691 {
1750 if (!transitWasReset) 1692 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1751 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1693 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1694 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1752 } 1695 }
1753 1696
1754 return agent; 1697 // Next, let's close the child agent connections that are too far away.
1698 uint neighbourx;
1699 uint neighboury;
1700
1701 Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1702
1703 neighbourx /= Constants.RegionSize;
1704 neighboury /= Constants.RegionSize;
1705
1706 agent.CloseChildAgents(neighbourx, neighboury);
1707
1708 AgentHasMovedAway(agent, false);
1709
1710 // the user may change their profile information in other region,
1711 // so the userinfo in UserProfileCache is not reliable any more, delete it
1712 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1713// if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1714// {
1715// m_log.DebugFormat(
1716// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1717// }
1718
1719 //m_log.Debug("AFTER CROSS");
1720 //Scene.DumpChildrenSeeds(UUID);
1721 //DumpKnownRegions();
1722
1723 return;
1755 } 1724 }
1756 1725
1757 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 1726 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
@@ -1822,10 +1791,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1822 agent.Id0 = currentAgentCircuit.Id0; 1791 agent.Id0 = currentAgentCircuit.Id0;
1823 } 1792 }
1824 1793
1825 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 1794 IPEndPoint external = region.ExternalEndPoint;
1826 d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, 1795 if (external != null)
1796 {
1797 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1798 d.BeginInvoke(sp, agent, region, external, true,
1827 InformClientOfNeighbourCompleted, 1799 InformClientOfNeighbourCompleted,
1828 d); 1800 d);
1801 }
1829 } 1802 }
1830 #endregion 1803 #endregion
1831 1804
@@ -2422,30 +2395,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2422 Utils.LongToUInts(newRegionHandle, out x, out y); 2395 Utils.LongToUInts(newRegionHandle, out x, out y);
2423 GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); 2396 GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
2424 2397
2425 if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) 2398 if (destination != null)
2426 { 2399 {
2427 m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}",grp.UUID); 2400 if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2401 return; // we did it
2402 }
2428 2403
2429 // We are going to move the object back to the old position so long as the old position 2404 // no one or failed lets go back and tell physics to go on
2430 // is in the region 2405 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
2431 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X,1.0f,(float)Constants.RegionSize-1); 2406 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
2432 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y,1.0f,(float)Constants.RegionSize-1); 2407 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f);
2433 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z,1.0f,4096.0f);
2434 2408
2435 grp.RootPart.GroupPosition = oldGroupPosition; 2409 grp.AbsolutePosition = oldGroupPosition;
2410 grp.Velocity = Vector3.Zero;
2436 2411
2437 // Need to turn off the physics flags, otherwise the object will continue to attempt to 2412 if (grp.RootPart.PhysActor != null)
2438 // move out of the region creating an infinite loop of failed attempts to cross 2413 grp.RootPart.PhysActor.CrossingFailure();
2439 grp.UpdatePrimFlags(grp.RootPart.LocalId,false,grp.IsTemporary,grp.IsPhantom,false);
2440 2414
2441 if (grp.RootPart.KeyframeMotion != null) 2415 if (grp.RootPart.KeyframeMotion != null)
2442 grp.RootPart.KeyframeMotion.CrossingFailure(); 2416 grp.RootPart.KeyframeMotion.CrossingFailure();
2443 2417
2444 grp.ScheduleGroupForFullUpdate(); 2418 grp.ScheduleGroupForFullUpdate();
2445 }
2446 } 2419 }
2447 2420
2448 2421
2422
2449 /// <summary> 2423 /// <summary>
2450 /// Move the given scene object into a new region 2424 /// Move the given scene object into a new region
2451 /// </summary> 2425 /// </summary>
@@ -2496,17 +2470,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2496 grp, e); 2470 grp, e);
2497 } 2471 }
2498 } 2472 }
2473/*
2474 * done on caller ( not in attachments crossing for now)
2499 else 2475 else
2500 { 2476 {
2477
2501 if (!grp.IsDeleted) 2478 if (!grp.IsDeleted)
2502 { 2479 {
2503 PhysicsActor pa = grp.RootPart.PhysActor; 2480 PhysicsActor pa = grp.RootPart.PhysActor;
2504 if (pa != null) 2481 if (pa != null)
2482 {
2505 pa.CrossingFailure(); 2483 pa.CrossingFailure();
2484 if (grp.RootPart.KeyframeMotion != null)
2485 {
2486 // moved to KeyframeMotion.CrossingFailure
2487// grp.RootPart.Velocity = Vector3.Zero;
2488 grp.RootPart.KeyframeMotion.CrossingFailure();
2489// grp.SendGroupRootTerseUpdate();
2490 }
2491 }
2506 } 2492 }
2507 2493
2508 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp); 2494 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
2509 } 2495 }
2496 */
2510 } 2497 }
2511 else 2498 else
2512 { 2499 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index fc02916..e903383 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
294 id, m_mod.Scene.RegionInfo.RegionName, currentState)); 294 id, m_mod.Scene.RegionInfo.RegionName, currentState));
295 } 295 }
296 296
297 int count = 200; 297 int count = 400;
298 298
299 // There should be no race condition here since no other code should be removing the agent transfer or 299 // There should be no race condition here since no other code should be removing the agent transfer or
300 // changing the state to another other than Transferring => ReceivedAtDestination. 300 // changing the state to another other than Transferring => ReceivedAtDestination.
@@ -349,4 +349,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
349 } 349 }
350 } 350 }
351 } 351 }
352} \ No newline at end of file 352}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 76dbc72..1cf1884 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -313,6 +313,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
313 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout); 313 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout);
314 } 314 }
315 315
316 public void TriggerTeleportHome(UUID id, IClientAPI client)
317 {
318 TeleportHome(id, client);
319 }
320
316 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) 321 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
317 { 322 {
318 reason = "Please wear your grid's allowed appearance before teleporting to another grid"; 323 reason = "Please wear your grid's allowed appearance before teleporting to another grid";
@@ -431,11 +436,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
431 // return base.UpdateAgent(reg, finalDestination, agentData, sp); 436 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
432 //} 437 //}
433 438
434 public virtual void TriggerTeleportHome(UUID id, IClientAPI client)
435 {
436 TeleportHome(id, client);
437 }
438
439 public override bool TeleportHome(UUID id, IClientAPI client) 439 public override bool TeleportHome(UUID id, IClientAPI client)
440 { 440 {
441 m_log.DebugFormat( 441 m_log.DebugFormat(
@@ -483,9 +483,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
483 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}", 483 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}",
484 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName); 484 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName);
485 485
486 DoTeleport( 486 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
487 sp, homeGatekeeper, finalDestination,
488 position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
489 return true; 487 return true;
490 } 488 }
491 489
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 68e4e26..89bb037 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -183,44 +183,49 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
183 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) 183 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
184 return; 184 return;
185 185
186 if (transactionID == UUID.Zero) 186 InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId);
187 InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f);
188
189 if (folder == null || folder.Owner != remoteClient.AgentId)
190 return;
191
192 if (transactionID != UUID.Zero)
187 { 193 {
188 ScenePresence presence; 194 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
189 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 195 if (agentTransactions != null)
190 { 196 {
191 byte[] data = null; 197 if (agentTransactions.HandleItemCreationFromTransaction(
198 remoteClient, transactionID, folderID, callbackID, description,
199 name, invType, assetType, wearableType, nextOwnerMask))
200 return;
201 }
202 }
192 203
193 if (invType == (sbyte)InventoryType.Landmark && presence != null) 204 ScenePresence presence;
194 { 205 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
195 string suffix = string.Empty, prefix = string.Empty; 206 {
196 string strdata = GenerateLandmark(presence, out prefix, out suffix); 207 byte[] data = null;
197 data = Encoding.ASCII.GetBytes(strdata);
198 name = prefix + name;
199 description += suffix;
200 }
201 208
202 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 209 if (invType == (sbyte)InventoryType.Landmark && presence != null)
203 m_Scene.AssetService.Store(asset);
204 m_Scene.CreateNewInventoryItem(
205 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
206 name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
207 }
208 else
209 { 210 {
210 m_log.ErrorFormat( 211 string suffix = string.Empty, prefix = string.Empty;
211 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", 212 string strdata = GenerateLandmark(presence, out prefix, out suffix);
212 remoteClient.AgentId); 213 data = Encoding.ASCII.GetBytes(strdata);
214 name = prefix + name;
215 description += suffix;
213 } 216 }
217
218 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
219 m_Scene.AssetService.Store(asset);
220 m_Scene.CreateNewInventoryItem(
221 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
222 name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate,transactionID);
214 } 223 }
215 else 224 else
216 { 225 {
217 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; 226 m_log.ErrorFormat(
218 if (agentTransactions != null) 227 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
219 { 228 remoteClient.AgentId);
220 agentTransactions.HandleItemCreationFromTransaction(
221 remoteClient, transactionID, folderID, callbackID, description,
222 name, invType, assetType, wearableType, nextOwnerMask);
223 }
224 } 229 }
225 } 230 }
226 231
@@ -359,20 +364,38 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
359 { 364 {
360 if (objectGroup.RootPart.KeyframeMotion != null) 365 if (objectGroup.RootPart.KeyframeMotion != null)
361 objectGroup.RootPart.KeyframeMotion.Stop(); 366 objectGroup.RootPart.KeyframeMotion.Stop();
367 objectGroup.RootPart.SetForce(Vector3.Zero);
368 objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
362 objectGroup.RootPart.KeyframeMotion = null; 369 objectGroup.RootPart.KeyframeMotion = null;
363// Vector3 inventoryStoredPosition = new Vector3 370
364// (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 371 Vector3 inventoryStoredPosition = new Vector3
365// ? 250 372 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
366// : objectGroup.AbsolutePosition.X) 373 ? 250
367// , 374 : objectGroup.AbsolutePosition.X)
368// (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) 375 ,
369// ? 250 376 (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize)
370// : objectGroup.AbsolutePosition.Y, 377 ? 250
371// objectGroup.AbsolutePosition.Z); 378 : objectGroup.AbsolutePosition.Y,
372// 379 objectGroup.AbsolutePosition.Z);
373// originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 380
374// 381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
375// objectGroup.AbsolutePosition = inventoryStoredPosition; 382 //originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
383
384 // Restore attachment data after trip through the sim
385 if (objectGroup.RootPart.AttachPoint > 0)
386 {
387 inventoryStoredPosition = objectGroup.RootPart.AttachOffset;
388 inventoryStoredRotation = objectGroup.RootPart.AttachRotation;
389 }
390
391 // Trees could be attached and it's been done, but it makes
392 // no sense. State must be preserved because it's the tree type
393 if (objectGroup.RootPart.Shape.PCode != (byte)PCode.Tree &&
394 objectGroup.RootPart.Shape.PCode != (byte)PCode.NewTree)
395 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
396
397 objectGroup.AbsolutePosition = inventoryStoredPosition;
398 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
376 399
377 // Make sure all bits but the ones we want are clear 400 // Make sure all bits but the ones we want are clear
378 // on take. 401 // on take.
@@ -491,8 +514,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
491 IClientAPI remoteClient) 514 IClientAPI remoteClient)
492 { 515 {
493 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; 516 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7;
517 // For the porposes of inventory, an object is modify if the prims
518 // are modify. This allows renaming an object that contains no
519 // mod items.
494 foreach (SceneObjectGroup grp in objsForEffectivePermissions) 520 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
495 effectivePerms &= grp.GetEffectivePermissions(); 521 {
522 uint groupPerms = grp.GetEffectivePermissions(true);
523 if ((grp.RootPart.BaseMask & (uint)PermissionMask.Modify) != 0)
524 groupPerms |= (uint)PermissionMask.Modify;
525
526 effectivePerms &= groupPerms;
527 }
496 effectivePerms |= (uint)PermissionMask.Move; 528 effectivePerms |= (uint)PermissionMask.Move;
497 529
498 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 530 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
@@ -673,7 +705,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
673 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) 705 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
674 { 706 {
675 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 707 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
676 folder = m_Scene.InventoryService.GetFolder(f); 708 if (f != null)
709 folder = m_Scene.InventoryService.GetFolder(f);
677 710
678 if(folder.Type == 14 || folder.Type == 16) 711 if(folder.Type == 14 || folder.Type == 16)
679 { 712 {
@@ -709,16 +742,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
709 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 742 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
710 { 743 {
711// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 744// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
712
713 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 745 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
714 item = m_Scene.InventoryService.GetItem(item); 746 item = m_Scene.InventoryService.GetItem(item);
715 747
716 if (item == null) 748 if (item == null)
717 { 749 {
718 m_log.WarnFormat(
719 "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()",
720 itemID, remoteClient.Name);
721
722 return null; 750 return null;
723 } 751 }
724 752
@@ -766,9 +794,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
766 XmlDocument doc = new XmlDocument(); 794 XmlDocument doc = new XmlDocument();
767 doc.LoadXml(xmlData); 795 doc.LoadXml(xmlData);
768 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); 796 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
797 Vector3 rez_pos;
769 if (e == null || attachment) // Single 798 if (e == null || attachment) // Single
770 { 799 {
771 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 800 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
801 if (!attachment)
802 {
803 g.RootPart.AttachPoint = g.RootPart.Shape.State;
804 g.RootPart.AttachOffset = g.AbsolutePosition;
805 g.RootPart.AttachRotation = g.GroupRotation;
806 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
807 g.RootPart.Shape.PCode != (byte)PCode.Tree)
808 g.RootPart.Shape.State = 0;
809 }
772 810
773 objlist.Add(g); 811 objlist.Add(g);
774 veclist.Add(Vector3.Zero); 812 veclist.Add(Vector3.Zero);
@@ -778,6 +816,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
778 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 816 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
779 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 817 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false);
780 pos.Z += offsetHeight; 818 pos.Z += offsetHeight;
819 rez_pos = pos;
781 } 820 }
782 else 821 else
783 { 822 {
@@ -792,12 +831,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
792 BypassRayCast, bRayEndIsIntersection, true, 831 BypassRayCast, bRayEndIsIntersection, true,
793 bbox, false); 832 bbox, false);
794 833
834 rez_pos = pos;
835
795 pos -= bbox / 2; 836 pos -= bbox / 2;
796 837
797 XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); 838 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
798 foreach (XmlNode n in groups) 839 foreach (XmlNode n in groups)
799 { 840 {
800 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); 841 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
842 g.RootPart.AttachPoint = g.RootPart.Shape.State;
843 g.RootPart.AttachOffset = g.AbsolutePosition;
844 g.RootPart.AttachRotation = g.GroupRotation;
845 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
846 g.RootPart.Shape.PCode != (byte)PCode.Tree)
847 g.RootPart.Shape.State = 0;
801 848
802 objlist.Add(g); 849 objlist.Add(g);
803 XmlElement el = (XmlElement)n; 850 XmlElement el = (XmlElement)n;
@@ -817,12 +864,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
817 } 864 }
818 } 865 }
819 866
820 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) 867 int primcount = 0;
868 foreach (SceneObjectGroup g in objlist)
869 primcount += g.PrimCount;
870
871 if (!m_Scene.Permissions.CanRezObject(
872 primcount, remoteClient.AgentId, rez_pos)
873 && !attachment)
874 {
875 // The client operates in no fail mode. It will
876 // have already removed the item from the folder
877 // if it's no copy.
878 // Put it back if it's not an attachment
879 //
880 if (item != null)
881 {
882 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
883 remoteClient.SendBulkUpdateInventory(item);
884 }
885
886 return null;
887 }
888
889 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, rez_pos, veclist, attachment))
821 return null; 890 return null;
822 891
823 for (int i = 0; i < objlist.Count; i++) 892 for (int i = 0; i < objlist.Count; i++)
824 { 893 {
825 group = objlist[i]; 894 group = objlist[i];
895 SceneObjectPart rootPart = group.RootPart;
826 896
827// m_log.DebugFormat( 897// m_log.DebugFormat(
828// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", 898// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
@@ -883,8 +953,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
883 953
884 if (!attachment) 954 if (!attachment)
885 { 955 {
886 SceneObjectPart rootPart = group.RootPart;
887
888 if (rootPart.Shape.PCode == (byte)PCode.Prim) 956 if (rootPart.Shape.PCode == (byte)PCode.Prim)
889 group.ClearPartAttachmentData(); 957 group.ClearPartAttachmentData();
890 958
@@ -902,6 +970,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
902// remoteClient.Name); 970// remoteClient.Name);
903 } 971 }
904 972
973 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
974
905 if (item != null) 975 if (item != null)
906 DoPostRezWhenFromItem(item, attachment); 976 DoPostRezWhenFromItem(item, attachment);
907 977
@@ -986,8 +1056,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
986 { 1056 {
987 rootPart.Name = item.Name; 1057 rootPart.Name = item.Name;
988 rootPart.Description = item.Description; 1058 rootPart.Description = item.Description;
989 rootPart.ObjectSaleType = item.SaleType; 1059 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
990 rootPart.SalePrice = item.SalePrice; 1060 {
1061 rootPart.ObjectSaleType = item.SaleType;
1062 rootPart.SalePrice = item.SalePrice;
1063 }
991 } 1064 }
992 1065
993 so.FromFolderID = item.Folder; 1066 so.FromFolderID = item.Folder;
@@ -997,7 +1070,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
997// rootPart.OwnerID, item.Owner, item.CurrentPermissions); 1070// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
998 1071
999 if ((rootPart.OwnerID != item.Owner) || 1072 if ((rootPart.OwnerID != item.Owner) ||
1000 (item.CurrentPermissions & 16) != 0) 1073 (item.CurrentPermissions & 16) != 0 ||
1074 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
1001 { 1075 {
1002 //Need to kill the for sale here 1076 //Need to kill the for sale here
1003 rootPart.ObjectSaleType = 0; 1077 rootPart.ObjectSaleType = 0;
@@ -1007,31 +1081,43 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1007 { 1081 {
1008 foreach (SceneObjectPart part in so.Parts) 1082 foreach (SceneObjectPart part in so.Parts)
1009 { 1083 {
1010 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
1011 {
1012 part.EveryoneMask = item.EveryOnePermissions;
1013 part.NextOwnerMask = item.NextPermissions;
1014 }
1015 part.GroupMask = 0; // DO NOT propagate here 1084 part.GroupMask = 0; // DO NOT propagate here
1085
1086 part.LastOwnerID = part.OwnerID;
1087 part.OwnerID = item.Owner;
1088 part.Inventory.ChangeInventoryOwner(item.Owner);
1016 } 1089 }
1017 1090
1018 so.ApplyNextOwnerPermissions(); 1091 so.ApplyNextOwnerPermissions();
1092
1093 // In case the user has changed flags on a received item
1094 // we have to apply those changes after the slam. Else we
1095 // get a net loss of permissions
1096 foreach (SceneObjectPart part in so.Parts)
1097 {
1098 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
1099 {
1100 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1101 part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
1102 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1103 part.NextOwnerMask = item.NextPermissions & part.BaseMask;
1104 }
1105 }
1019 } 1106 }
1020 } 1107 }
1021 1108 else
1022 foreach (SceneObjectPart part in so.Parts)
1023 { 1109 {
1024 part.FromUserInventoryItemID = fromUserInventoryItemId; 1110 foreach (SceneObjectPart part in so.Parts)
1025
1026 if ((part.OwnerID != item.Owner) ||
1027 (item.CurrentPermissions & 16) != 0)
1028 { 1111 {
1029 part.Inventory.ChangeInventoryOwner(item.Owner); 1112 part.FromUserInventoryItemID = fromUserInventoryItemId;
1030 part.GroupMask = 0; // DO NOT propagate here 1113
1114 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1115 part.EveryoneMask = item.EveryOnePermissions;
1116 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1117 part.NextOwnerMask = item.NextPermissions;
1118 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
1119 part.GroupMask = item.GroupPermissions;
1031 } 1120 }
1032
1033 part.EveryoneMask = item.EveryOnePermissions;
1034 part.NextOwnerMask = item.NextPermissions;
1035 } 1121 }
1036 1122
1037 rootPart.TrimPermissions(); 1123 rootPart.TrimPermissions();
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index 97227b3..f196973 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -136,9 +136,9 @@ namespace OpenSim.Region.CoreModules.Hypergrid
136 } 136 }
137 } 137 }
138 138
139 protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 139 protected override List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
140 { 140 {
141 List<MapBlockData> mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 141 List<MapBlockData> mapBlocks = base.GetAndSendBlocksInternal(remoteClient, minX, minY, maxX, maxY, flag);
142 lock (m_SeenMapBlocks) 142 lock (m_SeenMapBlocks)
143 { 143 {
144 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) 144 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId))
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 1a62405..6eb25ef 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -28,15 +28,12 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Linq;
32using System.Net; 31using System.Net;
33using System.Net.Mail; 32using System.Net.Mail;
34using System.Net.Security; 33using System.Net.Security;
35using System.Reflection;
36using System.Text; 34using System.Text;
37using System.Threading; 35using System.Threading;
38using System.Security.Cryptography.X509Certificates; 36using System.Security.Cryptography.X509Certificates;
39using log4net;
40using Nini.Config; 37using Nini.Config;
41using OpenMetaverse; 38using OpenMetaverse;
42using OpenSim.Framework; 39using OpenSim.Framework;
@@ -45,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
47using Mono.Addins; 44using Mono.Addins;
45using Amib.Threading;
48 46
49/***************************************************** 47/*****************************************************
50 * 48 *
@@ -105,6 +103,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
105 private Dictionary<UUID, HttpRequestClass> m_pendingRequests; 103 private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
106 private Scene m_scene; 104 private Scene m_scene;
107 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); 105 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
106 public static SmartThreadPool ThreadPool = null;
108 107
109 public HttpRequestModule() 108 public HttpRequestModule()
110 { 109 {
@@ -253,29 +252,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
253 return reqID; 252 return reqID;
254 } 253 }
255 254
256 public void StopHttpRequestsForScript(UUID id) 255 public void StopHttpRequest(uint m_localID, UUID m_itemID)
257 { 256 {
258 if (m_pendingRequests != null) 257 if (m_pendingRequests != null)
259 { 258 {
260 List<UUID> keysToRemove = null;
261
262 lock (HttpListLock) 259 lock (HttpListLock)
263 { 260 {
264 foreach (HttpRequestClass req in m_pendingRequests.Values) 261 HttpRequestClass tmpReq;
262 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
265 { 263 {
266 if (req.ItemID == id) 264 tmpReq.Stop();
267 { 265 m_pendingRequests.Remove(m_itemID);
268 req.Stop();
269
270 if (keysToRemove == null)
271 keysToRemove = new List<UUID>();
272
273 keysToRemove.Add(req.ReqID);
274 }
275 } 266 }
276
277 if (keysToRemove != null)
278 keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove));
279 } 267 }
280 } 268 }
281 } 269 }
@@ -293,13 +281,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
293 { 281 {
294 lock (HttpListLock) 282 lock (HttpListLock)
295 { 283 {
296 foreach (HttpRequestClass req in m_pendingRequests.Values) 284 foreach (UUID luid in m_pendingRequests.Keys)
297 { 285 {
298 if (req.Finished) 286 HttpRequestClass tmpReq;
299 return req; 287
288 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
289 {
290 if (tmpReq.Finished)
291 {
292 return tmpReq;
293 }
294 }
300 } 295 }
301 } 296 }
302
303 return null; 297 return null;
304 } 298 }
305 299
@@ -326,7 +320,30 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
326 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 320 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
327 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 321 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
328 322
323 int maxThreads = 50;
324
325 IConfig httpConfig = config.Configs["HttpRequestModule"];
326 if (httpConfig != null)
327 {
328 maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
329 }
330
329 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 331 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
332
333 // First instance sets this up for all sims
334 if (ThreadPool == null)
335 {
336 STPStartInfo startInfo = new STPStartInfo();
337 startInfo.IdleTimeout = 20000;
338 startInfo.MaxWorkerThreads = maxThreads;
339 startInfo.MinWorkerThreads = 5;
340 startInfo.ThreadPriority = ThreadPriority.BelowNormal;
341 startInfo.StartSuspended = true;
342
343 ThreadPool = new SmartThreadPool(startInfo);
344
345 ThreadPool.Start();
346 }
330 } 347 }
331 348
332 public void AddRegion(Scene scene) 349 public void AddRegion(Scene scene)
@@ -370,8 +387,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
370 387
371 public class HttpRequestClass: IServiceRequest 388 public class HttpRequestClass: IServiceRequest
372 { 389 {
373// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
374
375 // Constants for parameters 390 // Constants for parameters
376 // public const int HTTP_BODY_MAXLENGTH = 2; 391 // public const int HTTP_BODY_MAXLENGTH = 2;
377 // public const int HTTP_METHOD = 0; 392 // public const int HTTP_METHOD = 0;
@@ -392,6 +407,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
392 public string HttpMIMEType = "text/plain;charset=utf-8"; 407 public string HttpMIMEType = "text/plain;charset=utf-8";
393 public int HttpTimeout; 408 public int HttpTimeout;
394 public bool HttpVerifyCert = true; 409 public bool HttpVerifyCert = true;
410 public IWorkItemResult WorkItem = null;
411
395 //public bool HttpVerboseThrottle = true; // not implemented 412 //public bool HttpVerboseThrottle = true; // not implemented
396 public List<string> HttpCustomHeaders = null; 413 public List<string> HttpCustomHeaders = null;
397 public bool HttpPragmaNoCache = true; 414 public bool HttpPragmaNoCache = true;
@@ -419,7 +436,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
419 get { return _reqID; } 436 get { return _reqID; }
420 set { _reqID = value; } 437 set { _reqID = value; }
421 } 438 }
422 public WebRequest Request; 439 public HttpWebRequest Request;
423 public string ResponseBody; 440 public string ResponseBody;
424 public List<string> ResponseMetadata; 441 public List<string> ResponseMetadata;
425 public Dictionary<string, string> ResponseHeaders; 442 public Dictionary<string, string> ResponseHeaders;
@@ -428,14 +445,38 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
428 445
429 public void Process() 446 public void Process()
430 { 447 {
448 _finished = false;
449
450 lock (HttpRequestModule.ThreadPool)
451 WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
452 }
453
454 private object StpSendWrapper(object o)
455 {
431 SendRequest(); 456 SendRequest();
457 return null;
432 } 458 }
433 459
460 /*
461 * TODO: More work on the response codes. Right now
462 * returning 200 for success or 499 for exception
463 */
464
434 public void SendRequest() 465 public void SendRequest()
435 { 466 {
467 HttpWebResponse response = null;
468 StringBuilder sb = new StringBuilder();
469 byte[] buf = new byte[8192];
470 string tempString = null;
471 int count = 0;
472
436 try 473 try
437 { 474 {
438 Request = WebRequest.Create(Url); 475 Request = (HttpWebRequest) WebRequest.Create(Url);
476
477 //This works around some buggy HTTP Servers like Lighttpd
478 Request.ServicePoint.Expect100Continue = false;
479
439 Request.Method = HttpMethod; 480 Request.Method = HttpMethod;
440 Request.ContentType = HttpMIMEType; 481 Request.ContentType = HttpMIMEType;
441 482
@@ -443,7 +484,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
443 { 484 {
444 // We could hijack Connection Group Name to identify 485 // We could hijack Connection Group Name to identify
445 // a desired security exception. But at the moment we'll use a dummy header instead. 486 // a desired security exception. But at the moment we'll use a dummy header instead.
446// Request.ConnectionGroupName = "NoVerify";
447 Request.Headers.Add("NoVerifyCert", "true"); 487 Request.Headers.Add("NoVerifyCert", "true");
448 } 488 }
449// else 489// else
@@ -473,17 +513,14 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
473 } 513 }
474 } 514 }
475 515
476 if (ResponseHeaders != null) 516 foreach (KeyValuePair<string, string> entry in ResponseHeaders)
477 { 517 if (entry.Key.ToLower().Equals("user-agent"))
478 foreach (KeyValuePair<string, string> entry in ResponseHeaders) 518 Request.UserAgent = entry.Value;
479 if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) 519 else
480 ((HttpWebRequest)Request).UserAgent = entry.Value; 520 Request.Headers[entry.Key] = entry.Value;
481 else
482 Request.Headers[entry.Key] = entry.Value;
483 }
484 521
485 // Encode outbound data 522 // Encode outbound data
486 if (OutboundBody != null && OutboundBody.Length > 0) 523 if (OutboundBody.Length > 0)
487 { 524 {
488 byte[] data = Util.UTF8.GetBytes(OutboundBody); 525 byte[] data = Util.UTF8.GetBytes(OutboundBody);
489 526
@@ -493,12 +530,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
493 bstream.Close(); 530 bstream.Close();
494 } 531 }
495 532
533 Request.Timeout = HttpTimeout;
496 try 534 try
497 { 535 {
498 IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); 536 // execute the request
499 537 response = (HttpWebResponse) Request.GetResponse();
500 ThreadPool.RegisterWaitForSingleObject(
501 result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true);
502 } 538 }
503 catch (WebException e) 539 catch (WebException e)
504 { 540 {
@@ -506,82 +542,91 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
506 { 542 {
507 throw; 543 throw;
508 } 544 }
545 response = (HttpWebResponse)e.Response;
546 }
509 547
510 HttpWebResponse response = (HttpWebResponse)e.Response; 548 Status = (int)response.StatusCode;
511 549
512 Status = (int)response.StatusCode; 550 Stream resStream = response.GetResponseStream();
513 ResponseBody = response.StatusDescription;
514 _finished = true;
515 }
516 }
517 catch (Exception e)
518 {
519// m_log.Debug(
520// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e);
521 551
522 Status = (int)OSHttpStatusCode.ClientErrorJoker; 552 do
523 ResponseBody = e.Message; 553 {
524 _finished = true; 554 // fill the buffer with data
525 } 555 count = resStream.Read(buf, 0, buf.Length);
526 }
527 556
528 private void ResponseCallback(IAsyncResult ar) 557 // make sure we read some data
529 { 558 if (count != 0)
530 HttpWebResponse response = null; 559 {
560 // translate from bytes to ASCII text
561 tempString = Util.UTF8.GetString(buf, 0, count);
531 562
532 try 563 // continue building the string
564 sb.Append(tempString);
565 if (sb.Length > 2048)
566 break;
567 }
568 } while (count > 0); // any more data to read?
569
570 ResponseBody = sb.ToString().Replace("\r", "");
571 }
572 catch (WebException e)
533 { 573 {
534 try 574 if (e.Status == WebExceptionStatus.ProtocolError)
535 {
536 response = (HttpWebResponse)Request.EndGetResponse(ar);
537 }
538 catch (WebException e)
539 { 575 {
540 if (e.Status != WebExceptionStatus.ProtocolError) 576 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
577 Status = (int)webRsp.StatusCode;
578 try
541 { 579 {
542 throw; 580 using (Stream responseStream = webRsp.GetResponseStream())
581 {
582 ResponseBody = responseStream.GetStreamString();
583 }
584 }
585 catch
586 {
587 ResponseBody = webRsp.StatusDescription;
543 } 588 }
544 589 }
545 response = (HttpWebResponse)e.Response; 590 else
591 {
592 Status = (int)OSHttpStatusCode.ClientErrorJoker;
593 ResponseBody = e.Message;
546 } 594 }
547 595
548 Status = (int)response.StatusCode; 596 if (ResponseBody == null)
597 ResponseBody = String.Empty;
549 598
550 using (Stream stream = response.GetResponseStream()) 599 _finished = true;
551 { 600 return;
552 StreamReader reader = new StreamReader(stream, Encoding.UTF8);
553 ResponseBody = reader.ReadToEnd();
554 }
555 } 601 }
556 catch (Exception e) 602 catch (Exception e)
557 { 603 {
558 Status = (int)OSHttpStatusCode.ClientErrorJoker; 604 // Don't crash on anything else
559 ResponseBody = e.Message;
560
561// m_log.Debug(
562// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e);
563 } 605 }
564 finally 606 finally
565 { 607 {
566 if (response != null) 608 if (response != null)
567 response.Close(); 609 response.Close();
568
569 _finished = true;
570 } 610 }
571 }
572 611
573 private void TimeoutCallback(object state, bool timedOut) 612 if (ResponseBody == null)
574 { 613 ResponseBody = String.Empty;
575 if (timedOut) 614
576 Request.Abort(); 615 _finished = true;
577 } 616 }
578 617
579 public void Stop() 618 public void Stop()
580 { 619 {
581// m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); 620 try
582 621 {
583 if (Request != null) 622 if (!WorkItem.Cancel())
584 Request.Abort(); 623 {
624 WorkItem.Cancel(true);
625 }
626 }
627 catch (Exception)
628 {
629 }
585 } 630 }
586 } 631 }
587} \ No newline at end of file 632}
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 99a3122..1983fed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -42,40 +42,16 @@ using OpenSim.Region.Framework.Scenes;
42 42
43namespace OpenSim.Region.CoreModules.Scripting.LSLHttp 43namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
44{ 44{
45 /// <summary>
46 /// Data describing an external URL set up by a script.
47 /// </summary>
48 public class UrlData 45 public class UrlData
49 { 46 {
50 /// <summary>
51 /// Scene object part hosting the script
52 /// </summary>
53 public UUID hostID; 47 public UUID hostID;
54
55 /// <summary>
56 /// The item ID of the script that requested the URL.
57 /// </summary>
58 public UUID itemID; 48 public UUID itemID;
59
60 /// <summary>
61 /// The script engine that runs the script.
62 /// </summary>
63 public IScriptModule engine; 49 public IScriptModule engine;
64
65 /// <summary>
66 /// The generated URL.
67 /// </summary>
68 public string url; 50 public string url;
69
70 /// <summary>
71 /// The random UUID component of the generated URL.
72 /// </summary>
73 public UUID urlcode; 51 public UUID urlcode;
74
75 /// <summary>
76 /// The external requests currently being processed or awaiting retrieval for this URL.
77 /// </summary>
78 public Dictionary<UUID, RequestData> requests; 52 public Dictionary<UUID, RequestData> requests;
53 public bool isSsl;
54 public Scene scene;
79 } 55 }
80 56
81 public class RequestData 57 public class RequestData
@@ -89,7 +65,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
89 //public ManualResetEvent ev; 65 //public ManualResetEvent ev;
90 public bool requestDone; 66 public bool requestDone;
91 public int startTime; 67 public int startTime;
68 public bool responseSent;
92 public string uri; 69 public string uri;
70 public bool allowResponseType = false;
71 public UUID hostID;
72 public Scene scene;
93 } 73 }
94 74
95 /// <summary> 75 /// <summary>
@@ -102,20 +82,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
102 LogManager.GetLogger( 82 LogManager.GetLogger(
103 MethodBase.GetCurrentMethod().DeclaringType); 83 MethodBase.GetCurrentMethod().DeclaringType);
104 84
105 /// <summary> 85 private Dictionary<UUID, UrlData> m_RequestMap =
106 /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID 86 new Dictionary<UUID, UrlData>();
107 /// randomly generated when a request is received for this URL.
108 /// </summary>
109 /// <remarks>
110 /// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with
111 /// m_UrlMap
112 /// </remarks>
113 private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>();
114 87
115 /// <summary> 88 private Dictionary<string, UrlData> m_UrlMap =
116 /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL 89 new Dictionary<string, UrlData>();
117 /// </summary>
118 private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>();
119 90
120 private uint m_HttpsPort = 0; 91 private uint m_HttpsPort = 0;
121 private IHttpServer m_HttpServer = null; 92 private IHttpServer m_HttpServer = null;
@@ -126,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
126 /// <summary> 97 /// <summary>
127 /// The default maximum number of urls 98 /// The default maximum number of urls
128 /// </summary> 99 /// </summary>
129 public const int DefaultTotalUrls = 100; 100 public const int DefaultTotalUrls = 15000;
130 101
131 /// <summary> 102 /// <summary>
132 /// Maximum number of external urls that can be set up by this module. 103 /// Maximum number of external urls that can be set up by this module.
@@ -204,6 +175,17 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
204 175
205 public void RemoveRegion(Scene scene) 176 public void RemoveRegion(Scene scene)
206 { 177 {
178 // Drop references to that scene
179 foreach (KeyValuePair<string, UrlData> kvp in m_UrlMap)
180 {
181 if (kvp.Value.scene == scene)
182 kvp.Value.scene = null;
183 }
184 foreach (KeyValuePair<UUID, UrlData> kvp in m_RequestMap)
185 {
186 if (kvp.Value.scene == scene)
187 kvp.Value.scene = null;
188 }
207 } 189 }
208 190
209 public void Close() 191 public void Close()
@@ -221,7 +203,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
221 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 203 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
222 return urlcode; 204 return urlcode;
223 } 205 }
224 string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; 206 string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString();
225 207
226 UrlData urlData = new UrlData(); 208 UrlData urlData = new UrlData();
227 urlData.hostID = host.UUID; 209 urlData.hostID = host.UUID;
@@ -229,20 +211,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
229 urlData.engine = engine; 211 urlData.engine = engine;
230 urlData.url = url; 212 urlData.url = url;
231 urlData.urlcode = urlcode; 213 urlData.urlcode = urlcode;
214 urlData.isSsl = false;
232 urlData.requests = new Dictionary<UUID, RequestData>(); 215 urlData.requests = new Dictionary<UUID, RequestData>();
233 216 urlData.scene = host.ParentGroup.Scene;
217
234 m_UrlMap[url] = urlData; 218 m_UrlMap[url] = urlData;
235 219
236 string uri = "/lslhttp/" + urlcode.ToString() + "/"; 220 string uri = "/lslhttp/" + urlcode.ToString();
237 221
238 PollServiceEventArgs args 222 PollServiceEventArgs args
239 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); 223 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
240 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
241 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
242 226
243 m_log.DebugFormat( 227// m_log.DebugFormat(
244 "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", 228// "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}",
245 uri, itemID, host.Name, host.LocalId); 229// uri, itemID, host.Name, host.LocalId);
246 230
247 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 231 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
248 } 232 }
@@ -267,7 +251,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
267 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 251 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
268 return urlcode; 252 return urlcode;
269 } 253 }
270 string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; 254 string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString();
271 255
272 UrlData urlData = new UrlData(); 256 UrlData urlData = new UrlData();
273 urlData.hostID = host.UUID; 257 urlData.hostID = host.UUID;
@@ -275,20 +259,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
275 urlData.engine = engine; 259 urlData.engine = engine;
276 urlData.url = url; 260 urlData.url = url;
277 urlData.urlcode = urlcode; 261 urlData.urlcode = urlcode;
262 urlData.isSsl = true;
278 urlData.requests = new Dictionary<UUID, RequestData>(); 263 urlData.requests = new Dictionary<UUID, RequestData>();
279 264
265
280 m_UrlMap[url] = urlData; 266 m_UrlMap[url] = urlData;
281 267
282 string uri = "/lslhttps/" + urlcode.ToString() + "/"; 268 string uri = "/lslhttps/" + urlcode.ToString();
283 269
284 PollServiceEventArgs args 270 PollServiceEventArgs args
285 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); 271 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
286 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
287 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
288 274
289 m_log.DebugFormat( 275// m_log.DebugFormat(
290 "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", 276// "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}",
291 uri, itemID, host.Name, host.LocalId); 277// uri, itemID, host.Name, host.LocalId);
292 278
293 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 279 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
294 } 280 }
@@ -307,12 +293,15 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
307 return; 293 return;
308 } 294 }
309 295
310 foreach (UUID req in data.requests.Keys) 296 lock (m_RequestMap)
311 m_RequestMap.Remove(req); 297 {
312 298 foreach (UUID req in data.requests.Keys)
313 m_log.DebugFormat( 299 m_RequestMap.Remove(req);
314 "[URL MODULE]: Releasing url {0} for {1} in {2}", 300 }
315 url, data.itemID, data.hostID); 301
302// m_log.DebugFormat(
303// "[URL MODULE]: Releasing url {0} for {1} in {2}",
304// url, data.itemID, data.hostID);
316 305
317 RemoveUrl(data); 306 RemoveUrl(data);
318 m_UrlMap.Remove(url); 307 m_UrlMap.Remove(url);
@@ -337,29 +326,39 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
337 326
338 public void HttpResponse(UUID request, int status, string body) 327 public void HttpResponse(UUID request, int status, string body)
339 { 328 {
340 lock (m_UrlMap) 329 lock (m_RequestMap)
341 { 330 {
342 if (m_RequestMap.ContainsKey(request)) 331 if (m_RequestMap.ContainsKey(request))
343 { 332 {
344 UrlData urlData = m_RequestMap[request]; 333 UrlData urlData = m_RequestMap[request];
345 string responseBody = body; 334 if (!urlData.requests[request].responseSent)
346 if (urlData.requests[request].responseType.Equals("text/plain"))
347 { 335 {
348 string value; 336 string responseBody = body;
349 if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) 337
338 // If we have no OpenID from built-in browser, disable this
339 if (!urlData.requests[request].allowResponseType)
340 urlData.requests[request].responseType = "text/plain";
341
342 if (urlData.requests[request].responseType.Equals("text/plain"))
350 { 343 {
351 if (value != null && value.IndexOf("MSIE") >= 0) 344 string value;
345 if (urlData.requests[request].headers.TryGetValue("user-agent", out value))
352 { 346 {
353 // wrap the html escaped response if the target client is IE 347 if (value != null && value.IndexOf("MSIE") >= 0)
354 // It ignores "text/plain" if the body is html 348 {
355 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; 349 // wrap the html escaped response if the target client is IE
350 // It ignores "text/plain" if the body is html
351 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>";
352 }
356 } 353 }
357 } 354 }
355
356 urlData.requests[request].responseCode = status;
357 urlData.requests[request].responseBody = body;
358 //urlData.requests[request].ev.Set();
359 urlData.requests[request].requestDone = true;
360 urlData.requests[request].responseSent = true;
358 } 361 }
359 urlData.requests[request].responseCode = status;
360 urlData.requests[request].responseBody = responseBody;
361 //urlData.requests[request].ev.Set();
362 urlData.requests[request].requestDone =true;
363 } 362 }
364 else 363 else
365 { 364 {
@@ -370,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
370 369
371 public string GetHttpHeader(UUID requestId, string header) 370 public string GetHttpHeader(UUID requestId, string header)
372 { 371 {
373 lock (m_UrlMap) 372 lock (m_RequestMap)
374 { 373 {
375 if (m_RequestMap.ContainsKey(requestId)) 374 if (m_RequestMap.ContainsKey(requestId))
376 { 375 {
@@ -384,7 +383,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
384 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); 383 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
385 } 384 }
386 } 385 }
387
388 return String.Empty; 386 return String.Empty;
389 } 387 }
390 388
@@ -408,8 +406,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
408 { 406 {
409 RemoveUrl(url.Value); 407 RemoveUrl(url.Value);
410 removeURLs.Add(url.Key); 408 removeURLs.Add(url.Key);
411 foreach (UUID req in url.Value.requests.Keys) 409 lock (m_RequestMap)
412 m_RequestMap.Remove(req); 410 {
411 foreach (UUID req in url.Value.requests.Keys)
412 m_RequestMap.Remove(req);
413 }
413 } 414 }
414 } 415 }
415 416
@@ -430,9 +431,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
430 { 431 {
431 RemoveUrl(url.Value); 432 RemoveUrl(url.Value);
432 removeURLs.Add(url.Key); 433 removeURLs.Add(url.Key);
433 434 lock (m_RequestMap)
434 foreach (UUID req in url.Value.requests.Keys) 435 {
435 m_RequestMap.Remove(req); 436 foreach (UUID req in url.Value.requests.Keys)
437 m_RequestMap.Remove(req);
438 }
436 } 439 }
437 } 440 }
438 441
@@ -441,123 +444,128 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
441 } 444 }
442 } 445 }
443 446
447
444 private void RemoveUrl(UrlData data) 448 private void RemoveUrl(UrlData data)
445 { 449 {
446 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); 450 if (data.isSsl)
451 m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/");
452 else
453 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
447 } 454 }
448 455
449 private Hashtable NoEvents(UUID requestID, UUID sessionID) 456 private Hashtable NoEvents(UUID requestID, UUID sessionID)
450 { 457 {
451 Hashtable response = new Hashtable(); 458 Hashtable response = new Hashtable();
452 UrlData urlData; 459 UrlData url;
453 460 int startTime = 0;
454 lock (m_UrlMap) 461 lock (m_RequestMap)
455 { 462 {
456 // We need to return a 404 here in case the request URL was removed at exactly the same time that a
457 // request was made. In this case, the request thread can outrace llRemoveURL() and still be polling
458 // for the request ID.
459 if (!m_RequestMap.ContainsKey(requestID)) 463 if (!m_RequestMap.ContainsKey(requestID))
460 {
461 response["int_response_code"] = 404;
462 response["str_response_string"] = "";
463 response["keepalive"] = false;
464 response["reusecontext"] = false;
465
466 return response; 464 return response;
467 } 465 url = m_RequestMap[requestID];
466 startTime = url.requests[requestID].startTime;
467 }
468 468
469 urlData = m_RequestMap[requestID]; 469 if (System.Environment.TickCount - startTime > 25000)
470 {
471 response["int_response_code"] = 500;
472 response["str_response_string"] = "Script timeout";
473 response["content_type"] = "text/plain";
474 response["keepalive"] = false;
475 response["reusecontext"] = false;
470 476
471 if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) 477 //remove from map
478 lock (url.requests)
479 {
480 url.requests.Remove(requestID);
481 }
482 lock (m_RequestMap)
472 { 483 {
473 response["int_response_code"] = 500;
474 response["str_response_string"] = "Script timeout";
475 response["content_type"] = "text/plain";
476 response["keepalive"] = false;
477 response["reusecontext"] = false;
478
479 //remove from map
480 urlData.requests.Remove(requestID);
481 m_RequestMap.Remove(requestID); 484 m_RequestMap.Remove(requestID);
482
483 return response;
484 } 485 }
486
487 return response;
485 } 488 }
486 489
490
487 return response; 491 return response;
488 } 492 }
489 493
490 private bool HasEvents(UUID requestID, UUID sessionID) 494 private bool HasEvents(UUID requestID, UUID sessionID)
491 { 495 {
492 lock (m_UrlMap) 496 UrlData url=null;
497
498 lock (m_RequestMap)
493 { 499 {
494 // We return true here because an external URL request that happened at the same time as an llRemoveURL()
495 // can still make it through to HttpRequestHandler(). That will return without setting up a request
496 // when it detects that the URL has been removed. The poller, however, will continue to ask for
497 // events for that request, so here we will signal that there are events and in GetEvents we will
498 // return a 404.
499 if (!m_RequestMap.ContainsKey(requestID)) 500 if (!m_RequestMap.ContainsKey(requestID))
500 { 501 {
501 return true; 502 return false;
502 } 503 }
503 504 url = m_RequestMap[requestID];
504 UrlData urlData = m_RequestMap[requestID]; 505 }
505 506 lock (url.requests)
506 if (!urlData.requests.ContainsKey(requestID)) 507 {
508 if (!url.requests.ContainsKey(requestID))
507 { 509 {
508 return true; 510 return false;
509 } 511 }
510 512 else
511 // Trigger return of timeout response.
512 if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
513 { 513 {
514 return true; 514 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
515 {
516 return true;
517 }
518 if (url.requests[requestID].requestDone)
519 return true;
520 else
521 return false;
515 } 522 }
516
517 return urlData.requests[requestID].requestDone;
518 } 523 }
519 } 524 }
520
521 private Hashtable GetEvents(UUID requestID, UUID sessionID) 525 private Hashtable GetEvents(UUID requestID, UUID sessionID)
522 { 526 {
523 Hashtable response; 527 UrlData url = null;
528 RequestData requestData = null;
524 529
525 lock (m_UrlMap) 530 lock (m_RequestMap)
526 { 531 {
527 UrlData url = null;
528 RequestData requestData = null;
529
530 if (!m_RequestMap.ContainsKey(requestID)) 532 if (!m_RequestMap.ContainsKey(requestID))
531 return NoEvents(requestID, sessionID); 533 return NoEvents(requestID,sessionID);
532
533 url = m_RequestMap[requestID]; 534 url = m_RequestMap[requestID];
535 }
536 lock (url.requests)
537 {
534 requestData = url.requests[requestID]; 538 requestData = url.requests[requestID];
539 }
540
541 if (!requestData.requestDone)
542 return NoEvents(requestID,sessionID);
543
544 Hashtable response = new Hashtable();
535 545
536 if (!requestData.requestDone) 546 if (System.Environment.TickCount - requestData.startTime > 25000)
537 return NoEvents(requestID, sessionID); 547 {
538 548 response["int_response_code"] = 500;
539 response = new Hashtable(); 549 response["str_response_string"] = "Script timeout";
540 550 response["content_type"] = "text/plain";
541 if (System.Environment.TickCount - requestData.startTime > 25000)
542 {
543 response["int_response_code"] = 500;
544 response["str_response_string"] = "Script timeout";
545 response["content_type"] = "text/plain";
546 response["keepalive"] = false;
547 response["reusecontext"] = false;
548 return response;
549 }
550
551 //put response
552 response["int_response_code"] = requestData.responseCode;
553 response["str_response_string"] = requestData.responseBody;
554 response["content_type"] = requestData.responseType;
555 // response["content_type"] = "text/plain";
556 response["keepalive"] = false; 551 response["keepalive"] = false;
557 response["reusecontext"] = false; 552 response["reusecontext"] = false;
558 553 return response;
559 //remove from map 554 }
555 //put response
556 response["int_response_code"] = requestData.responseCode;
557 response["str_response_string"] = requestData.responseBody;
558 response["content_type"] = requestData.responseType;
559 response["keepalive"] = false;
560 response["reusecontext"] = false;
561
562 //remove from map
563 lock (url.requests)
564 {
560 url.requests.Remove(requestID); 565 url.requests.Remove(requestID);
566 }
567 lock (m_RequestMap)
568 {
561 m_RequestMap.Remove(requestID); 569 m_RequestMap.Remove(requestID);
562 } 570 }
563 571
@@ -566,41 +574,45 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
566 574
567 public void HttpRequestHandler(UUID requestID, Hashtable request) 575 public void HttpRequestHandler(UUID requestID, Hashtable request)
568 { 576 {
569 string uri = request["uri"].ToString(); 577 lock (request)
570 bool is_ssl = uri.Contains("lslhttps");
571
572 try
573 { 578 {
574 Hashtable headers = (Hashtable)request["headers"]; 579 string uri = request["uri"].ToString();
580 bool is_ssl = uri.Contains("lslhttps");
575 581
576// string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; 582 try
577
578 int pos1 = uri.IndexOf("/");// /lslhttp
579 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
580 int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
581 string uri_tmp = uri.Substring(0, pos3 + 1);
582 //HTTP server code doesn't provide us with QueryStrings
583 string pathInfo;
584 string queryString;
585 queryString = "";
586
587 pathInfo = uri.Substring(pos3);
588
589 UrlData urlData = null;
590
591 lock (m_UrlMap)
592 { 583 {
593 string url; 584 Hashtable headers = (Hashtable)request["headers"];
594 585
595 if (is_ssl) 586// string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/";
596 url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; 587
588 int pos1 = uri.IndexOf("/");// /lslhttp
589 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
590 int pos3 = pos2 + 37; // /lslhttp/urlcode
591 string uri_tmp = uri.Substring(0, pos3);
592 //HTTP server code doesn't provide us with QueryStrings
593 string pathInfo;
594 string queryString;
595 queryString = "";
596
597 pathInfo = uri.Substring(pos3);
598
599 UrlData url = null;
600 string urlkey;
601 if (!is_ssl)
602 urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
603 //m_UrlMap[];
597 else 604 else
598 url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; 605 urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
599 606
600 // Avoid a race - the request URL may have been released via llRequestUrl() whilst this 607 if (m_UrlMap.ContainsKey(urlkey))
601 // request was being processed. 608 {
602 if (!m_UrlMap.TryGetValue(url, out urlData)) 609 url = m_UrlMap[urlkey];
610 }
611 else
612 {
613 //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString());
603 return; 614 return;
615 }
604 616
605 //for llGetHttpHeader support we need to store original URI here 617 //for llGetHttpHeader support we need to store original URI here
606 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers 618 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
@@ -611,6 +623,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
611 requestData.requestDone = false; 623 requestData.requestDone = false;
612 requestData.startTime = System.Environment.TickCount; 624 requestData.startTime = System.Environment.TickCount;
613 requestData.uri = uri; 625 requestData.uri = uri;
626 requestData.hostID = url.hostID;
627 requestData.scene = url.scene;
614 if (requestData.headers == null) 628 if (requestData.headers == null)
615 requestData.headers = new Dictionary<string, string>(); 629 requestData.headers = new Dictionary<string, string>();
616 630
@@ -619,8 +633,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
619 string key = (string)header.Key; 633 string key = (string)header.Key;
620 string value = (string)header.Value; 634 string value = (string)header.Value;
621 requestData.headers.Add(key, value); 635 requestData.headers.Add(key, value);
636 if (key == "cookie")
637 {
638 string[] parts = value.Split(new char[] {'='});
639 if (parts[0] == "agni_sl_session_id" && parts.Length > 1)
640 {
641 string cookie = Uri.UnescapeDataString(parts[1]);
642 string[] crumbs = cookie.Split(new char[] {':'});
643 UUID owner;
644 if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner))
645 {
646 if (crumbs[1].Length == 32)
647 {
648 Scene scene = requestData.scene;
649 if (scene != null)
650 {
651 SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID);
652 if (host != null)
653 {
654 if (host.OwnerID == owner)
655 requestData.allowResponseType = true;
656 }
657 }
658 }
659 }
660 }
661 }
622 } 662 }
623
624 foreach (DictionaryEntry de in request) 663 foreach (DictionaryEntry de in request)
625 { 664 {
626 if (de.Key.ToString() == "querystringkeys") 665 if (de.Key.ToString() == "querystringkeys")
@@ -631,13 +670,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
631 if (request.ContainsKey(key)) 670 if (request.ContainsKey(key))
632 { 671 {
633 string val = (String)request[key]; 672 string val = (String)request[key];
634 queryString = queryString + key + "=" + val + "&"; 673 if (key != "")
674 {
675 queryString = queryString + key + "=" + val + "&";
676 }
677 else
678 {
679 queryString = queryString + val + "&";
680 }
635 } 681 }
636 } 682 }
637
638 if (queryString.Length > 1) 683 if (queryString.Length > 1)
639 queryString = queryString.Substring(0, queryString.Length - 1); 684 queryString = queryString.Substring(0, queryString.Length - 1);
685
640 } 686 }
687
641 } 688 }
642 689
643 //if this machine is behind DNAT/port forwarding, currently this is being 690 //if this machine is behind DNAT/port forwarding, currently this is being
@@ -645,23 +692,34 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
645 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; 692 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
646 requestData.headers["x-path-info"] = pathInfo; 693 requestData.headers["x-path-info"] = pathInfo;
647 requestData.headers["x-query-string"] = queryString; 694 requestData.headers["x-query-string"] = queryString;
648 requestData.headers["x-script-url"] = urlData.url; 695 requestData.headers["x-script-url"] = url.url;
649 696
650 urlData.requests.Add(requestID, requestData); 697 //requestData.ev = new ManualResetEvent(false);
651 m_RequestMap.Add(requestID, urlData); 698 lock (url.requests)
652 } 699 {
700 url.requests.Add(requestID, requestData);
701 }
702 lock (m_RequestMap)
703 {
704 //add to request map
705 m_RequestMap.Add(requestID, url);
706 }
653 707
654 urlData.engine.PostScriptEvent( 708 url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
655 urlData.itemID, 709
656 "http_request", 710 //send initial response?
657 new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); 711// Hashtable response = new Hashtable();
658 } 712
659 catch (Exception we) 713 return;
660 { 714
661 //Hashtable response = new Hashtable(); 715 }
662 m_log.Warn("[HttpRequestHandler]: http-in request failed"); 716 catch (Exception we)
663 m_log.Warn(we.Message); 717 {
664 m_log.Warn(we.StackTrace); 718 //Hashtable response = new Hashtable();
719 m_log.Warn("[HttpRequestHandler]: http-in request failed");
720 m_log.Warn(we.Message);
721 m_log.Warn(we.StackTrace);
722 }
665 } 723 }
666 } 724 }
667 725
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 6da2222..ad33f23 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -271,6 +271,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
271 return "modInvokeR"; 271 return "modInvokeR";
272 else if (sid.ReturnType == typeof(object[])) 272 else if (sid.ReturnType == typeof(object[]))
273 return "modInvokeL"; 273 return "modInvokeL";
274 else if (sid.ReturnType == typeof(void))
275 return "modInvokeN";
274 276
275 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); 277 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
276 } 278 }
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 4cecd85..2fc89fc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -861,4 +861,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
861 return null; 861 return null;
862 } 862 }
863 } 863 }
864} \ No newline at end of file 864}
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 2c2c99c..87a0537 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -96,6 +96,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
96 // private static readonly ILog m_log = 96 // private static readonly ILog m_log =
97 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 97 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98 98
99 private const int DEBUG_CHANNEL = 2147483647;
100
99 private ListenerManager m_listenerManager; 101 private ListenerManager m_listenerManager;
100 private Queue m_pending; 102 private Queue m_pending;
101 private Queue m_pendingQ; 103 private Queue m_pendingQ;
@@ -366,67 +368,60 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
366 /// <param name='msg'> 368 /// <param name='msg'>
367 /// Message. 369 /// Message.
368 /// </param> 370 /// </param>
369 public void DeliverMessageTo(UUID target, int channel, Vector3 pos, 371 public bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg, out string error)
370 string name, UUID id, string msg)
371 { 372 {
373 error = null;
374
375 if (channel == DEBUG_CHANNEL)
376 return true;
377
372 // Is id an avatar? 378 // Is id an avatar?
373 ScenePresence sp = m_scene.GetScenePresence(target); 379 ScenePresence sp = m_scene.GetScenePresence(target);
374 380
375 if (sp != null) 381 if (sp != null)
376 { 382 {
377 // ignore if a child agent this is restricted to inside one 383 // Send message to avatar
378 // region
379 if (sp.IsChildAgent)
380 return;
381
382 // Send message to the avatar.
383 // Channel zero only goes to the avatar
384 // non zero channel messages only go to the attachments
385 if (channel == 0) 384 if (channel == 0)
386 { 385 {
387 m_scene.SimChatToAgent(target, Utils.StringToBytes(msg), 386 // Channel 0 goes to viewer ONLY
388 pos, name, id, false); 387 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
388 return true;
389 } 389 }
390 else
391 {
392 List<SceneObjectGroup> attachments = sp.GetAttachments();
393 if (attachments.Count == 0)
394 return;
395 390
396 // Get uuid of attachments 391 List<SceneObjectGroup> attachments = sp.GetAttachments();
397 List<UUID> targets = new List<UUID>();
398 foreach (SceneObjectGroup sog in attachments)
399 {
400 if (!sog.IsDeleted)
401 targets.Add(sog.UUID);
402 }
403 392
404 // Need to check each attachment 393 if (attachments.Count == 0)
405 foreach (ListenerInfo li 394 return true;
406 in m_listenerManager.GetListeners(UUID.Zero,
407 channel, name, id, msg))
408 {
409 if (li.GetHostID().Equals(id))
410 continue;
411 395
412 if (m_scene.GetSceneObjectPart( 396 // Get uuid of attachments
413 li.GetHostID()) == null) 397 List<UUID> targets = new List<UUID>();
414 { 398 foreach (SceneObjectGroup sog in attachments)
415 continue; 399 {
416 } 400 if (!sog.IsDeleted)
401 targets.Add(sog.UUID);
402 }
417 403
418 if (targets.Contains(li.GetHostID())) 404 // Need to check each attachment
419 QueueMessage(new ListenerInfo(li, name, id, msg)); 405 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
420 } 406 {
407 if (li.GetHostID().Equals(id))
408 continue;
409
410 if (m_scene.GetSceneObjectPart(li.GetHostID()) == null)
411 continue;
412
413 if (targets.Contains(li.GetHostID()))
414 QueueMessage(new ListenerInfo(li, name, id, msg));
421 } 415 }
422 416
423 return; 417 return true;
424 } 418 }
425 419
426 // No avatar found so look for an object 420 SceneObjectPart part = m_scene.GetSceneObjectPart(target);
427 foreach (ListenerInfo li 421 if (part == null) // Not even an object
428 in m_listenerManager.GetListeners(UUID.Zero, channel, 422 return true; // No error
429 name, id, msg)) 423
424 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
430 { 425 {
431 // Dont process if this message is from yourself! 426 // Dont process if this message is from yourself!
432 if (li.GetHostID().Equals(id)) 427 if (li.GetHostID().Equals(id))
@@ -444,7 +439,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
444 } 439 }
445 } 440 }
446 441
447 return; 442 return true;
448 } 443 }
449 444
450 protected void QueueMessage(ListenerInfo li) 445 protected void QueueMessage(ListenerInfo li)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
index 16f42a7..f027810 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
@@ -139,6 +139,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
139 139
140 #region IAuthenticationService 140 #region IAuthenticationService
141 141
142 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
143 {
144 // Not implemented at the regions
145 realID = UUID.Zero;
146 return string.Empty;
147 }
148
142 public string Authenticate(UUID principalID, string password, int lifetime) 149 public string Authenticate(UUID principalID, string password, int lifetime)
143 { 150 {
144 // Not implemented at the regions 151 // Not implemented at the regions
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 26d22b8..b61062f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -92,8 +92,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
92 if (config == null) 92 if (config == null)
93 return; 93 return;
94 94
95 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); 95 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime", "-1"));
96 if (refreshminutes <= 0) 96 if (refreshminutes < 0)
97 { 97 {
98 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled."); 98 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled.");
99 return; 99 return;
@@ -116,12 +116,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
116 return; 116 return;
117 } 117 }
118 118
119 m_refreshTimer.Enabled = true; 119 if (m_refreshtime > 0)
120 m_refreshTimer.AutoReset = true; 120 {
121 m_refreshTimer.Interval = m_refreshtime; 121 m_refreshTimer.Enabled = true;
122 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); 122 m_refreshTimer.AutoReset = true;
123 m_refreshTimer.Interval = m_refreshtime;
124 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
125 }
123 126
124 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}", 127 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0} min and service object {1}",
125 refreshminutes, service); 128 refreshminutes, service);
126 129
127 m_enabled = true; 130 m_enabled = true;
@@ -231,4 +234,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
231 } 234 }
232 } 235 }
233 } 236 }
234} \ No newline at end of file 237}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index e86d186..a9aa73c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -314,7 +314,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
314 m_scenes[destination.RegionID].IncomingCloseAgent(id, false, auth_token); 314 m_scenes[destination.RegionID].IncomingCloseAgent(id, false, auth_token);
315 return true; 315 return true;
316 } 316 }
317
318 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 317 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
319 return false; 318 return false;
320 } 319 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index f45f560..8bd1d10 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -239,7 +239,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
239 return false; 239 return false;
240 } 240 }
241 241
242
243 public bool CloseAgent(GridRegion destination, UUID id, string auth_token) 242 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
244 { 243 {
245 if (destination == null) 244 if (destination == null)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 529bfd7..ea4ade5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -129,6 +129,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
129 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner 129 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner
130 // user account service?! 130 // user account service?!
131 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService); 131 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService);
132 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
132 } 133 }
133 134
134 public void RemoveRegion(Scene scene) 135 public void RemoveRegion(Scene scene)
@@ -181,6 +182,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
181 return UserAccountService.GetUserAccount(scopeID, Email); 182 return UserAccountService.GetUserAccount(scopeID, Email);
182 } 183 }
183 184
185 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
186 {
187 return null;
188 }
189
184 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 190 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
185 { 191 {
186 return UserAccountService.GetUserAccounts(scopeID, query); 192 return UserAccountService.GetUserAccounts(scopeID, query);
@@ -195,4 +201,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
195 201
196 #endregion 202 #endregion
197 } 203 }
198} \ No newline at end of file 204}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index 5aa87d3..afbba30 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -34,6 +34,7 @@ using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Services.Connectors; 36using OpenSim.Services.Connectors;
37using OpenSim.Framework;
37 38
38using OpenMetaverse; 39using OpenMetaverse;
39 40
@@ -103,6 +104,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
103 return; 104 return;
104 105
105 scene.RegisterModuleInterface<IUserAccountService>(this); 106 scene.RegisterModuleInterface<IUserAccountService>(this);
107 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
108
109 scene.EventManager.OnNewClient += OnNewClient;
106 } 110 }
107 111
108 public void RemoveRegion(Scene scene) 112 public void RemoveRegion(Scene scene)
@@ -117,6 +121,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
117 return; 121 return;
118 } 122 }
119 123
124 // When a user actually enters the sim, clear them from
125 // cache so the sim will have the current values for
126 // flags, title, etc. And country, don't forget country!
127 private void OnNewClient(IClientAPI client)
128 {
129 m_Cache.Remove(client.Name);
130 }
131
120 #region Overwritten methods from IUserAccountService 132 #region Overwritten methods from IUserAccountService
121 133
122 public override UserAccount GetUserAccount(UUID scopeID, UUID userID) 134 public override UserAccount GetUserAccount(UUID scopeID, UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
index ddef75f..cbe2eaa 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
@@ -34,7 +34,7 @@ using log4net;
34 34
35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts 35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
36{ 36{
37 public class UserAccountCache 37 public class UserAccountCache : IUserAccountCacheModule
38 { 38 {
39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours! 39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours!
40 40
@@ -92,5 +92,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
92 92
93 return null; 93 return null;
94 } 94 }
95
96 public void Remove(string name)
97 {
98 if (!m_NameCache.Contains(name))
99 return;
100
101 UUID uuid = UUID.Zero;
102 if (m_NameCache.TryGetValue(name, out uuid))
103 {
104 m_NameCache.Remove(name);
105 m_UUIDCache.Remove(uuid);
106 }
107 }
95 } 108 }
96} 109}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 32d245f..fcfdf7c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -490,6 +490,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
490 // being no copy/no mod for everyone 490 // being no copy/no mod for everyone
491 lock (part.TaskInventory) 491 lock (part.TaskInventory)
492 { 492 {
493 if (!ResolveUserUuid(scene, part.CreatorID))
494 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
495
496 if (!ResolveUserUuid(scene, part.OwnerID))
497 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
498
499 if (!ResolveUserUuid(scene, part.LastOwnerID))
500 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
501
502 // And zap any troublesome sit target information
503 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
504 part.SitTargetPosition = new Vector3(0, 0, 0);
505
506 // Fix ownership/creator of inventory items
507 // Not doing so results in inventory items
508 // being no copy/no mod for everyone
509 part.TaskInventory.LockItemsForRead(true);
493 TaskInventoryDictionary inv = part.TaskInventory; 510 TaskInventoryDictionary inv = part.TaskInventory;
494 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 511 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
495 { 512 {
@@ -510,6 +527,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
510 if (!ResolveGroupUuid(kvp.Value.GroupID)) 527 if (!ResolveGroupUuid(kvp.Value.GroupID))
511 kvp.Value.GroupID = UUID.Zero; 528 kvp.Value.GroupID = UUID.Zero;
512 } 529 }
530 part.TaskInventory.LockItemsForRead(false);
513 } 531 }
514 } 532 }
515 533
@@ -899,4 +917,4 @@ namespace OpenSim.Region.CoreModules.World.Archiver
899 return dearchivedScenes; 917 return dearchivedScenes;
900 } 918 }
901 } 919 }
902} \ No newline at end of file 920}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 9600023..ada7ecc 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -271,18 +271,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
271 271
272 if (asset != null) 272 if (asset != null)
273 { 273 {
274 if (m_options.ContainsKey("verbose")) 274// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id);
275 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
276
277 m_foundAssetUuids.Add(asset.FullID); 275 m_foundAssetUuids.Add(asset.FullID);
278 276
279 m_assetsArchiver.WriteAsset(PostProcess(asset)); 277 m_assetsArchiver.WriteAsset(PostProcess(asset));
280 } 278 }
281 else 279 else
282 { 280 {
283 if (m_options.ContainsKey("verbose")) 281// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id);
284 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
285
286 m_notFoundAssetUuids.Add(new UUID(id)); 282 m_notFoundAssetUuids.Add(new UUID(id));
287 } 283 }
288 284
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 31547a6..1808fdd 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -331,6 +331,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
331 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 331 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
332 if (restartModule != null) 332 if (restartModule != null)
333 { 333 {
334 if (timeInSeconds == -1)
335 {
336 m_delayCount++;
337 if (m_delayCount > 3)
338 return;
339
340 restartModule.DelayRestart(3600, "Restart delayed by region manager");
341 return;
342 }
343
334 List<int> times = new List<int>(); 344 List<int> times = new List<int>();
335 while (timeInSeconds > 0) 345 while (timeInSeconds > 0)
336 { 346 {
@@ -1249,6 +1259,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
1249 flags |= RegionFlags.AllowParcelChanges; 1259 flags |= RegionFlags.AllowParcelChanges;
1250 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) 1260 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
1251 flags |= RegionFlags.BlockParcelSearch; 1261 flags |= RegionFlags.BlockParcelSearch;
1262 if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
1263 flags |= (RegionFlags)(1 << 11);
1264 if (Scene.RegionInfo.RegionSettings.Casino)
1265 flags |= (RegionFlags)(1 << 10);
1252 1266
1253 if (Scene.RegionInfo.RegionSettings.FixedSun) 1267 if (Scene.RegionInfo.RegionSettings.FixedSun)
1254 flags |= RegionFlags.SunFixed; 1268 flags |= RegionFlags.SunFixed;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 1789d6d..dbc9296 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -89,19 +89,21 @@ namespace OpenSim.Region.CoreModules.World.Land
89 /// <value> 89 /// <value>
90 /// Land objects keyed by local id 90 /// Land objects keyed by local id
91 /// </value> 91 /// </value>
92 private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); 92// private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
93
94 //ubit: removed the readonly so i can move it around
95 private Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
93 96
94 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 97 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
95 98
96 private bool m_allowedForcefulBans = true; 99 private bool m_allowedForcefulBans = true;
100 private UUID DefaultGodParcelGroup;
101 private string DefaultGodParcelName;
97 102
98 // caches ExtendedLandData 103 // caches ExtendedLandData
99 private Cache parcelInfoCache; 104 private Cache parcelInfoCache;
100 105 private Dictionary<UUID, Vector3> forcedPosition =
101 /// <summary> 106 new Dictionary<UUID, Vector3>();
102 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
103 /// </summary>
104 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
105 107
106 #region INonSharedRegionModule Members 108 #region INonSharedRegionModule Members
107 109
@@ -112,6 +114,12 @@ namespace OpenSim.Region.CoreModules.World.Land
112 114
113 public void Initialise(IConfigSource source) 115 public void Initialise(IConfigSource source)
114 { 116 {
117 IConfig cnf = source.Configs["LandManagement"];
118 if (cnf != null)
119 {
120 DefaultGodParcelGroup = new UUID(cnf.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
121 DefaultGodParcelName = cnf.GetString("DefaultAdministratorParcelName", "Default Parcel");
122 }
115 } 123 }
116 124
117 public void AddRegion(Scene scene) 125 public void AddRegion(Scene scene)
@@ -165,13 +173,6 @@ namespace OpenSim.Region.CoreModules.World.Land
165 m_scene.UnregisterModuleCommander(m_commander.Name); 173 m_scene.UnregisterModuleCommander(m_commander.Name);
166 } 174 }
167 175
168// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
169// {
170// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
171// reason = "You are not allowed to enter this sim.";
172// return nearestParcel != null;
173// }
174
175 /// <summary> 176 /// <summary>
176 /// Processes commandline input. Do not call directly. 177 /// Processes commandline input. Do not call directly.
177 /// </summary> 178 /// </summary>
@@ -216,7 +217,6 @@ namespace OpenSim.Region.CoreModules.World.Land
216 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 217 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
217 client.OnSetStartLocationRequest += ClientOnSetHome; 218 client.OnSetStartLocationRequest += ClientOnSetHome;
218 219
219
220 EntityBase presenceEntity; 220 EntityBase presenceEntity;
221 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 221 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
222 { 222 {
@@ -232,48 +232,6 @@ namespace OpenSim.Region.CoreModules.World.Land
232 232
233 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 233 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
234 { 234 {
235 //If we are forcing a position for them to go
236 if (forcedPosition.ContainsKey(remoteClient.AgentId))
237 {
238 ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
239
240 //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
241 //When the avatar walks into a ban line on the ground, it prevents getting stuck
242 agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
243
244 //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
245 if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2)
246 {
247// m_log.DebugFormat(
248// "[LAND MANAGEMENT MODULE]: Stopping force position of {0} because {1} is close enough to {2}",
249// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);
250
251 forcedPosition.Remove(remoteClient.AgentId);
252 }
253 //if we are far away, teleport
254 else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3)
255 {
256 Vector3 forcePosition = forcedPosition[remoteClient.AgentId];
257// m_log.DebugFormat(
258// "[LAND MANAGEMENT MODULE]: Teleporting out {0} because {1} is too far from avatar position {2}",
259// clientAvatar.Name, clientAvatar.AbsolutePosition, forcePosition);
260
261 m_scene.RequestTeleportLocation(remoteClient, m_scene.RegionInfo.RegionHandle,
262 forcePosition, clientAvatar.Lookat, (uint)Constants.TeleportFlags.ForceRedirect);
263
264 forcedPosition.Remove(remoteClient.AgentId);
265 }
266 else
267 {
268// m_log.DebugFormat(
269// "[LAND MANAGEMENT MODULE]: Forcing {0} from {1} to {2}",
270// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);
271
272 //Forces them toward the forced position we want if they aren't there yet
273 agentData.UseClientAgentPosition = true;
274 agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId];
275 }
276 }
277 } 235 }
278 236
279 public void Close() 237 public void Close()
@@ -298,6 +256,7 @@ namespace OpenSim.Region.CoreModules.World.Land
298 { 256 {
299 LandData newData = data.Copy(); 257 LandData newData = data.Copy();
300 newData.LocalID = local_id; 258 newData.LocalID = local_id;
259 ILandObject landobj = null;
301 260
302 ILandObject land; 261 ILandObject land;
303 lock (m_landList) 262 lock (m_landList)
@@ -337,14 +296,14 @@ namespace OpenSim.Region.CoreModules.World.Land
337 protected ILandObject CreateDefaultParcel() 296 protected ILandObject CreateDefaultParcel()
338 { 297 {
339 m_log.DebugFormat( 298 m_log.DebugFormat(
340 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); 299 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
341 300
342 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 301 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
343 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 302 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
344 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 303 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
345 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 304 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
346 305
347 return AddLandObject(fullSimParcel); 306 return AddLandObject(fullSimParcel);
348 } 307 }
349 308
350 public List<ILandObject> AllParcels() 309 public List<ILandObject> AllParcels()
@@ -393,10 +352,16 @@ namespace OpenSim.Region.CoreModules.World.Land
393 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 352 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
394 { 353 {
395 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 354 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
396 if (position.HasValue) 355
397 { 356 if (!position.HasValue)
398 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; 357 return;
399 } 358
359 bool isFlying = avatar.PhysicsActor.Flying;
360 avatar.RemoveFromPhysicalScene();
361
362 avatar.AbsolutePosition = (Vector3)position;
363
364 avatar.AddToPhysicalScene(isFlying);
400 } 365 }
401 366
402 public void SendYouAreRestrictedNotice(ScenePresence avatar) 367 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -416,29 +381,7 @@ namespace OpenSim.Region.CoreModules.World.Land
416 } 381 }
417 382
418 if (parcelAvatarIsEntering != null) 383 if (parcelAvatarIsEntering != null)
419 { 384 EnforceBans(parcelAvatarIsEntering, avatar);
420 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
421 {
422 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
423 {
424 SendYouAreBannedNotice(avatar);
425 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
426 }
427 else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
428 {
429 SendYouAreRestrictedNotice(avatar);
430 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
431 }
432 else
433 {
434 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
435 }
436 }
437 else
438 {
439 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
440 }
441 }
442 } 385 }
443 } 386 }
444 387
@@ -467,30 +410,51 @@ namespace OpenSim.Region.CoreModules.World.Land
467 410
468 public void SendLandUpdate(ScenePresence avatar, bool force) 411 public void SendLandUpdate(ScenePresence avatar, bool force)
469 { 412 {
413
414 /* stop sendind same data twice
415 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
416 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
417
418 if (over != null)
419 {
420
421 if (force)
422 {
423 if (!avatar.IsChildAgent)
424 {
425 over.SendLandUpdateToClient(avatar.ControllingClient);
426 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
427 m_scene.RegionInfo.RegionID);
428 }
429 }
430
431 if (avatar.currentParcelUUID != over.LandData.GlobalID)
432 {
433 if (!avatar.IsChildAgent)
434 {
435 over.SendLandUpdateToClient(avatar.ControllingClient);
436 avatar.currentParcelUUID = over.LandData.GlobalID;
437 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
438 m_scene.RegionInfo.RegionID);
439 }
440 }
441 */
442 if (avatar.IsChildAgent)
443 return;
444
470 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 445 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
471 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); 446 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
472 447
473 if (over != null) 448 if (over != null)
474 { 449 {
475 if (force) 450 bool NotsameID = (avatar.currentParcelUUID != over.LandData.GlobalID);
476 { 451 if (force || NotsameID)
477 if (!avatar.IsChildAgent)
478 {
479 over.SendLandUpdateToClient(avatar.ControllingClient);
480 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
481 m_scene.RegionInfo.RegionID);
482 }
483 }
484
485 if (avatar.currentParcelUUID != over.LandData.GlobalID)
486 { 452 {
487 if (!avatar.IsChildAgent) 453 over.SendLandUpdateToClient(avatar.ControllingClient);
488 { 454 if (NotsameID)
489 over.SendLandUpdateToClient(avatar.ControllingClient);
490 avatar.currentParcelUUID = over.LandData.GlobalID; 455 avatar.currentParcelUUID = over.LandData.GlobalID;
491 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, 456 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
492 m_scene.RegionInfo.RegionID); 457 m_scene.RegionInfo.RegionID);
493 }
494 } 458 }
495 } 459 }
496 } 460 }
@@ -542,6 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Land
542 //when we are finally in a safe place, lets release the forced position lock 506 //when we are finally in a safe place, lets release the forced position lock
543 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); 507 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
544 } 508 }
509 EnforceBans(parcel, clientAvatar);
545 } 510 }
546 } 511 }
547 512
@@ -692,27 +657,28 @@ namespace OpenSim.Region.CoreModules.World.Land
692 /// </summary> 657 /// </summary>
693 public void Clear(bool setupDefaultParcel) 658 public void Clear(bool setupDefaultParcel)
694 { 659 {
695 List<ILandObject> parcels; 660 Dictionary<int, ILandObject> landworkList;
661 // move to work pointer since we are deleting it all
696 lock (m_landList) 662 lock (m_landList)
697 { 663 {
698 parcels = new List<ILandObject>(m_landList.Values); 664 landworkList = m_landList;
665 m_landList = new Dictionary<int, ILandObject>();
699 } 666 }
700 667
701 foreach (ILandObject lo in parcels) 668 // this 2 methods have locks (now)
669 ResetSimLandObjects();
670
671 if (setupDefaultParcel)
672 CreateDefaultParcel();
673
674 // fire outside events unlocked
675 foreach (ILandObject lo in landworkList.Values)
702 { 676 {
703 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); 677 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID);
704 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); 678 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID);
705 } 679 }
680 landworkList.Clear();
706 681
707 lock (m_landList)
708 {
709 m_landList.Clear();
710
711 ResetSimLandObjects();
712 }
713
714 if (setupDefaultParcel)
715 CreateDefaultParcel();
716 } 682 }
717 683
718 private void performFinalLandJoin(ILandObject master, ILandObject slave) 684 private void performFinalLandJoin(ILandObject master, ILandObject slave)
@@ -759,7 +725,7 @@ namespace OpenSim.Region.CoreModules.World.Land
759 int x; 725 int x;
760 int y; 726 int y;
761 727
762 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 728 if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0)
763 return null; 729 return null;
764 730
765 try 731 try
@@ -809,14 +775,13 @@ namespace OpenSim.Region.CoreModules.World.Land
809 { 775 {
810 try 776 try
811 { 777 {
812 return m_landList[m_landIDList[x / 4, y / 4]]; 778 //if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4]))
779 return m_landList[m_landIDList[x / 4, y / 4]];
780 //else
781 // return null;
813 } 782 }
814 catch (IndexOutOfRangeException) 783 catch (IndexOutOfRangeException)
815 { 784 {
816// m_log.WarnFormat(
817// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}",
818// x, y, m_scene.RegionInfo.RegionName);
819
820 return null; 785 return null;
821 } 786 }
822 } 787 }
@@ -975,6 +940,8 @@ namespace OpenSim.Region.CoreModules.World.Land
975 newLand.LandData.Name = newLand.LandData.Name; 940 newLand.LandData.Name = newLand.LandData.Name;
976 newLand.LandData.GlobalID = UUID.Random(); 941 newLand.LandData.GlobalID = UUID.Random();
977 newLand.LandData.Dwell = 0; 942 newLand.LandData.Dwell = 0;
943 // Clear "Show in search" on the cut out parcel to prevent double-charging
944 newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory;
978 945
979 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 946 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
980 947
@@ -1100,6 +1067,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1100 //Owner Flag 1067 //Owner Flag
1101 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1068 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1102 } 1069 }
1070 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1071 {
1072 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP);
1073 }
1103 else if (currentParcelBlock.LandData.SalePrice > 0 && 1074 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1104 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || 1075 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1105 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) 1076 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
@@ -1180,8 +1151,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1180 { 1151 {
1181 if (!temp.Contains(currentParcel)) 1152 if (!temp.Contains(currentParcel))
1182 { 1153 {
1183 currentParcel.ForceUpdateLandInfo(); 1154 if (!currentParcel.IsEitherBannedOrRestricted(remote_client.AgentId))
1184 temp.Add(currentParcel); 1155 {
1156 currentParcel.ForceUpdateLandInfo();
1157 temp.Add(currentParcel);
1158 }
1185 } 1159 }
1186 } 1160 }
1187 } 1161 }
@@ -1400,8 +1374,26 @@ namespace OpenSim.Region.CoreModules.World.Land
1400 1374
1401 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1375 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1402 { 1376 {
1403// m_log.DebugFormat( 1377 Dictionary<int, ILandObject> landworkList;
1404// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name); 1378 // move to work pointer since we are deleting it all
1379 lock (m_landList)
1380 {
1381 landworkList = m_landList;
1382 m_landList = new Dictionary<int, ILandObject>();
1383 }
1384
1385 //Remove all the land objects in the sim and then process our new data
1386 foreach (int n in landworkList.Keys)
1387 {
1388 m_scene.EventManager.TriggerLandObjectRemoved(landworkList[n].LandData.GlobalID);
1389 }
1390 landworkList.Clear();
1391
1392 lock (m_landList)
1393 {
1394 m_landIDList.Initialize();
1395 m_landList.Clear();
1396 }
1405 1397
1406 for (int i = 0; i < data.Count; i++) 1398 for (int i = 0; i < data.Count; i++)
1407 IncomingLandObjectFromStorage(data[i]); 1399 IncomingLandObjectFromStorage(data[i]);
@@ -1409,10 +1401,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1409 1401
1410 public void IncomingLandObjectFromStorage(LandData data) 1402 public void IncomingLandObjectFromStorage(LandData data)
1411 { 1403 {
1404
1412 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1405 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1413 new_land.LandData = data.Copy(); 1406 new_land.LandData = data.Copy();
1414 new_land.SetLandBitmapFromByteArray(); 1407 new_land.SetLandBitmapFromByteArray();
1415 AddLandObject(new_land); 1408 AddLandObject(new_land);
1409 new_land.SendLandUpdateToAvatarsOverMe();
1416 } 1410 }
1417 1411
1418 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1412 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1743,7 +1737,86 @@ namespace OpenSim.Region.CoreModules.World.Land
1743 1737
1744 UpdateLandObject(localID, land.LandData); 1738 UpdateLandObject(localID, land.LandData);
1745 } 1739 }
1746 1740
1741 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1742 {
1743 ILandObject land = null;
1744 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1745 foreach (ILandObject landObject in Land)
1746 {
1747 if (landObject.LandData.LocalID == landID)
1748 {
1749 land = landObject;
1750 }
1751 }
1752 land.DeedToGroup(DefaultGodParcelGroup);
1753 land.LandData.Name = DefaultGodParcelName;
1754 land.SendLandUpdateToAvatarsOverMe();
1755 }
1756
1757 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1758 {
1759 ScenePresence SP;
1760 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1761 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1762 if (SP.UserLevel != 0)
1763 {
1764 if (flags == 0) //All parcels, scripted or not
1765 {
1766 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1767 {
1768 if (e.OwnerID == targetID)
1769 {
1770 returns.Add(e);
1771 }
1772 }
1773 );
1774 }
1775 if (flags == 4) //All parcels, scripted object
1776 {
1777 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1778 {
1779 if (e.OwnerID == targetID)
1780 {
1781 if (e.ContainsScripts())
1782 {
1783 returns.Add(e);
1784 }
1785 }
1786 }
1787 );
1788 }
1789 if (flags == 4) //not target parcel, scripted object
1790 {
1791 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1792 {
1793 if (e.OwnerID == targetID)
1794 {
1795 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1796 if (landobject.LandData.OwnerID != e.OwnerID)
1797 {
1798 if (e.ContainsScripts())
1799 {
1800 returns.Add(e);
1801 }
1802 }
1803 }
1804 }
1805 );
1806 }
1807 foreach (SceneObjectGroup ol in returns)
1808 {
1809 ReturnObject(ol, client);
1810 }
1811 }
1812 }
1813 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1814 {
1815 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1816 objs[0] = obj;
1817 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1818 }
1819
1747 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); 1820 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1748 1821
1749 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 1822 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
@@ -1779,7 +1852,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1779 } 1852 }
1780 } 1853 }
1781 } 1854 }
1782
1783 private void OnEndParcelFrozen(object avatar) 1855 private void OnEndParcelFrozen(object avatar)
1784 { 1856 {
1785 ScenePresence targetAvatar = (ScenePresence)avatar; 1857 ScenePresence targetAvatar = (ScenePresence)avatar;
@@ -1790,6 +1862,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1790 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false); 1862 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1791 } 1863 }
1792 1864
1865
1793 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 1866 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1794 { 1867 {
1795 ScenePresence targetAvatar = null; 1868 ScenePresence targetAvatar = null;
@@ -1809,12 +1882,13 @@ namespace OpenSim.Region.CoreModules.World.Land
1809 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) && 1882 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) &&
1810 !m_scene.Permissions.IsAdministrator(client.AgentId)) 1883 !m_scene.Permissions.IsAdministrator(client.AgentId))
1811 return; 1884 return;
1885
1812 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); 1886 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
1813 1887
1814 targetAvatar.TeleportWithMomentum(pos, null); 1888 targetAvatar.TeleportWithMomentum(pos, null);
1815 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); 1889 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
1816 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); 1890 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
1817 1891
1818 if ((flags & 1) != 0) // Ban TODO: Remove magic number 1892 if ((flags & 1) != 0) // Ban TODO: Remove magic number
1819 { 1893 {
1820 LandAccessEntry entry = new LandAccessEntry(); 1894 LandAccessEntry entry = new LandAccessEntry();
@@ -1872,7 +1946,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1872 m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel."); 1946 m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel.");
1873 } 1947 }
1874 1948
1875
1876 protected void InstallInterfaces() 1949 protected void InstallInterfaces()
1877 { 1950 {
1878 Command clearCommand 1951 Command clearCommand
@@ -1934,5 +2007,27 @@ namespace OpenSim.Region.CoreModules.World.Land
1934 2007
1935 MainConsole.Instance.Output(report.ToString()); 2008 MainConsole.Instance.Output(report.ToString());
1936 } 2009 }
2010
2011 public void EnforceBans(ILandObject land, ScenePresence avatar)
2012 {
2013 if (avatar.AbsolutePosition.Z > LandChannel.BAN_LINE_SAFETY_HIEGHT)
2014 return;
2015
2016 if (land.IsEitherBannedOrRestricted(avatar.UUID))
2017 {
2018 if (land.ContainsPoint(Convert.ToInt32(avatar.lastKnownAllowedPosition.X), Convert.ToInt32(avatar.lastKnownAllowedPosition.Y)))
2019 {
2020 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
2021 if (pos == null)
2022 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
2023 else
2024 ForceAvatarToPosition(avatar, (Vector3)pos);
2025 }
2026 else
2027 {
2028 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
2029 }
2030 }
2031 }
1937 } 2032 }
1938} 2033}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index e55c9ed..ce4bd0f 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -51,6 +51,7 @@ namespace OpenSim.Region.CoreModules.World.Land
51 private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; 51 private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
52 52
53 private int m_lastSeqId = 0; 53 private int m_lastSeqId = 0;
54 private int m_expiryCounter = 0;
54 55
55 protected LandData m_landData = new LandData(); 56 protected LandData m_landData = new LandData();
56 protected Scene m_scene; 57 protected Scene m_scene;
@@ -136,6 +137,8 @@ namespace OpenSim.Region.CoreModules.World.Land
136 else 137 else
137 LandData.GroupID = UUID.Zero; 138 LandData.GroupID = UUID.Zero;
138 LandData.IsGroupOwned = is_group_owned; 139 LandData.IsGroupOwned = is_group_owned;
140
141 m_scene.EventManager.OnFrame += OnFrame;
139 } 142 }
140 143
141 #endregion 144 #endregion
@@ -194,10 +197,27 @@ namespace OpenSim.Region.CoreModules.World.Land
194 else 197 else
195 { 198 {
196 // Normal Calculations 199 // Normal Calculations
197 int parcelMax = (int)(((float)LandData.Area / 65536.0f) 200 int parcelMax = (int)((long)LandData.Area
198 * (float)m_scene.RegionInfo.ObjectCapacity 201 * (long)m_scene.RegionInfo.ObjectCapacity
199 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 202 * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
200 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 203 / 65536L);
204 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
205 return parcelMax;
206 }
207 }
208
209 private int GetParcelBasePrimCount()
210 {
211 if (overrideParcelMaxPrimCount != null)
212 {
213 return overrideParcelMaxPrimCount(this);
214 }
215 else
216 {
217 // Normal Calculations
218 int parcelMax = (int)((long)LandData.Area
219 * (long)m_scene.RegionInfo.ObjectCapacity
220 / 65536L);
201 return parcelMax; 221 return parcelMax;
202 } 222 }
203 } 223 }
@@ -211,8 +231,9 @@ namespace OpenSim.Region.CoreModules.World.Land
211 else 231 else
212 { 232 {
213 //Normal Calculations 233 //Normal Calculations
214 int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) 234 int simMax = (int)((long)LandData.SimwideArea
215 * (float)m_scene.RegionInfo.ObjectCapacity); 235 * (long)m_scene.RegionInfo.ObjectCapacity / 65536L);
236 // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
216 return simMax; 237 return simMax;
217 } 238 }
218 } 239 }
@@ -242,7 +263,7 @@ namespace OpenSim.Region.CoreModules.World.Land
242 remote_client.SendLandProperties(seq_id, 263 remote_client.SendLandProperties(seq_id,
243 snap_selection, request_result, this, 264 snap_selection, request_result, this,
244 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, 265 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
245 GetParcelMaxPrimCount(), 266 GetParcelBasePrimCount(),
246 GetSimulatorMaxPrimCount(), regionFlags); 267 GetSimulatorMaxPrimCount(), regionFlags);
247 } 268 }
248 269
@@ -302,7 +323,7 @@ namespace OpenSim.Region.CoreModules.World.Land
302 323
303 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 324 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
304 ParcelFlags.AllowPublish | 325 ParcelFlags.AllowPublish |
305 ParcelFlags.MaturePublish); 326 ParcelFlags.MaturePublish) | (uint)(1 << 23);
306 } 327 }
307 328
308 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 329 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity))
@@ -414,6 +435,19 @@ namespace OpenSim.Region.CoreModules.World.Land
414 return false; 435 return false;
415 } 436 }
416 437
438 public bool CanBeOnThisLand(UUID avatar, float posHeight)
439 {
440 if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar))
441 {
442 return false;
443 }
444 else if (IsRestrictedFromLand(avatar))
445 {
446 return false;
447 }
448 return true;
449 }
450
417 public bool HasGroupAccess(UUID avatar) 451 public bool HasGroupAccess(UUID avatar)
418 { 452 {
419 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) 453 if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
@@ -1178,6 +1212,17 @@ namespace OpenSim.Region.CoreModules.World.Land
1178 1212
1179 #endregion 1213 #endregion
1180 1214
1215 private void OnFrame()
1216 {
1217 m_expiryCounter++;
1218
1219 if (m_expiryCounter >= 50)
1220 {
1221 ExpireAccessList();
1222 m_expiryCounter = 0;
1223 }
1224 }
1225
1181 private void ExpireAccessList() 1226 private void ExpireAccessList()
1182 { 1227 {
1183 List<LandAccessEntry> delete = new List<LandAccessEntry>(); 1228 List<LandAccessEntry> delete = new List<LandAccessEntry>();
@@ -1188,7 +1233,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1188 delete.Add(entry); 1233 delete.Add(entry);
1189 } 1234 }
1190 foreach (LandAccessEntry entry in delete) 1235 foreach (LandAccessEntry entry in delete)
1236 {
1191 LandData.ParcelAccessList.Remove(entry); 1237 LandData.ParcelAccessList.Remove(entry);
1238 ScenePresence presence;
1239
1240 if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
1241 {
1242 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1243 if (land.LandData.LocalID == LandData.LocalID)
1244 {
1245 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1246 presence.TeleportWithMomentum(pos, null);
1247 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1248 }
1249 }
1250 m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1251 }
1192 1252
1193 if (delete.Count > 0) 1253 if (delete.Count > 0)
1194 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this); 1254 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 9b51cc8..771fdd2 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -207,7 +207,7 @@ namespace OpenSim.Region.CoreModules.World.Land
207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
208 { 208 {
209 UUID landOwner = landData.OwnerID; 209 UUID landOwner = landData.OwnerID;
210 int partCount = obj.Parts.Length; 210 int partCount = obj.GetPartCount();
211 211
212 m_SimwideCounts[landOwner] += partCount; 212 m_SimwideCounts[landOwner] += partCount;
213 if (parcelCounts.Users.ContainsKey(obj.OwnerID)) 213 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
@@ -597,4 +597,4 @@ namespace OpenSim.Region.CoreModules.World.Land
597 } 597 }
598 } 598 }
599 } 599 }
600} \ No newline at end of file 600}
diff --git a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
index 89f3280..f13d648 100644
--- a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
+++ b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
@@ -190,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.LightShare
190 190
191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl) 191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl)
192 { 192 {
193 if (client == null)
194 return;
195
193 if (m_enableWindlight) 196 if (m_enableWindlight)
194 { 197 {
195 if (m_scene.RegionInfo.WindlightSettings.valid) 198 if (m_scene.RegionInfo.WindlightSettings.valid)
@@ -207,7 +210,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
207 210
208 private void EventManager_OnMakeRootAgent(ScenePresence presence) 211 private void EventManager_OnMakeRootAgent(ScenePresence presence)
209 { 212 {
210 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client"); 213 if (m_enableWindlight && m_scene.RegionInfo.WindlightSettings.valid)
214 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client");
211 SendProfileToClient(presence.ControllingClient); 215 SendProfileToClient(presence.ControllingClient);
212 } 216 }
213 217
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 22a53a8..28daf2f 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -177,6 +177,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
177 return false; 177 return false;
178 } 178 }
179 179
180 if ((perms & (uint)PermissionMask.Copy) == 0)
181 {
182 if (m_dialogModule != null)
183 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
184 return false;
185 }
186
180 AssetBase asset = m_scene.CreateAsset( 187 AssetBase asset = m_scene.CreateAsset(
181 group.GetPartName(localID), 188 group.GetPartName(localID),
182 group.GetPartDescription(localID), 189 group.GetPartDescription(localID),
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 249a40d..9c441ed 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -29,6 +29,8 @@ using System;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using System.Timers; 31using System.Timers;
32using System.IO;
33using System.Diagnostics;
32using System.Threading; 34using System.Threading;
33using System.Collections.Generic; 35using System.Collections.Generic;
34using log4net; 36using log4net;
@@ -57,13 +59,24 @@ namespace OpenSim.Region.CoreModules.World.Region
57 protected UUID m_Initiator; 59 protected UUID m_Initiator;
58 protected bool m_Notice = false; 60 protected bool m_Notice = false;
59 protected IDialogModule m_DialogModule = null; 61 protected IDialogModule m_DialogModule = null;
62 protected string m_MarkerPath = String.Empty;
63 private int[] m_CurrentAlerts = null;
60 64
61 public void Initialise(IConfigSource config) 65 public void Initialise(IConfigSource config)
62 { 66 {
67 IConfig restartConfig = config.Configs["RestartModule"];
68 if (restartConfig != null)
69 {
70 m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty);
71 }
63 } 72 }
64 73
65 public void AddRegion(Scene scene) 74 public void AddRegion(Scene scene)
66 { 75 {
76 if (m_MarkerPath != String.Empty)
77 File.Delete(Path.Combine(m_MarkerPath,
78 scene.RegionInfo.RegionID.ToString()));
79
67 m_Scene = scene; 80 m_Scene = scene;
68 81
69 scene.RegisterModuleInterface<IRestartModule>(this); 82 scene.RegisterModuleInterface<IRestartModule>(this);
@@ -122,6 +135,7 @@ namespace OpenSim.Region.CoreModules.World.Region
122 135
123 if (alerts == null) 136 if (alerts == null)
124 { 137 {
138 CreateMarkerFile();
125 m_Scene.RestartNow(); 139 m_Scene.RestartNow();
126 return; 140 return;
127 } 141 }
@@ -129,25 +143,28 @@ namespace OpenSim.Region.CoreModules.World.Region
129 m_Message = message; 143 m_Message = message;
130 m_Initiator = initiator; 144 m_Initiator = initiator;
131 m_Notice = notice; 145 m_Notice = notice;
146 m_CurrentAlerts = alerts;
132 m_Alerts = new List<int>(alerts); 147 m_Alerts = new List<int>(alerts);
133 m_Alerts.Sort(); 148 m_Alerts.Sort();
134 m_Alerts.Reverse(); 149 m_Alerts.Reverse();
135 150
136 if (m_Alerts[0] == 0) 151 if (m_Alerts[0] == 0)
137 { 152 {
153 CreateMarkerFile();
138 m_Scene.RestartNow(); 154 m_Scene.RestartNow();
139 return; 155 return;
140 } 156 }
141 157
142 int nextInterval = DoOneNotice(); 158 int nextInterval = DoOneNotice(true);
143 159
144 SetTimer(nextInterval); 160 SetTimer(nextInterval);
145 } 161 }
146 162
147 public int DoOneNotice() 163 public int DoOneNotice(bool sendOut)
148 { 164 {
149 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 165 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
150 { 166 {
167 CreateMarkerFile();
151 m_Scene.RestartNow(); 168 m_Scene.RestartNow();
152 return 0; 169 return 0;
153 } 170 }
@@ -168,34 +185,37 @@ namespace OpenSim.Region.CoreModules.World.Region
168 185
169 m_Alerts.RemoveAt(0); 186 m_Alerts.RemoveAt(0);
170 187
171 int minutes = currentAlert / 60; 188 if (sendOut)
172 string currentAlertString = String.Empty;
173 if (minutes > 0)
174 { 189 {
175 if (minutes == 1) 190 int minutes = currentAlert / 60;
176 currentAlertString += "1 minute"; 191 string currentAlertString = String.Empty;
177 else 192 if (minutes > 0)
178 currentAlertString += String.Format("{0} minutes", minutes); 193 {
194 if (minutes == 1)
195 currentAlertString += "1 minute";
196 else
197 currentAlertString += String.Format("{0} minutes", minutes);
198 if ((currentAlert % 60) != 0)
199 currentAlertString += " and ";
200 }
179 if ((currentAlert % 60) != 0) 201 if ((currentAlert % 60) != 0)
180 currentAlertString += " and "; 202 {
181 } 203 int seconds = currentAlert % 60;
182 if ((currentAlert % 60) != 0) 204 if (seconds == 1)
183 { 205 currentAlertString += "1 second";
184 int seconds = currentAlert % 60; 206 else
185 if (seconds == 1) 207 currentAlertString += String.Format("{0} seconds", seconds);
186 currentAlertString += "1 second"; 208 }
187 else
188 currentAlertString += String.Format("{0} seconds", seconds);
189 }
190 209
191 string msg = String.Format(m_Message, currentAlertString); 210 string msg = String.Format(m_Message, currentAlertString);
192 211
193 if (m_DialogModule != null && msg != String.Empty) 212 if (m_DialogModule != null && msg != String.Empty)
194 { 213 {
195 if (m_Notice) 214 if (m_Notice)
196 m_DialogModule.SendGeneralAlert(msg); 215 m_DialogModule.SendGeneralAlert(msg);
197 else 216 else
198 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg); 217 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg);
218 }
199 } 219 }
200 220
201 return currentAlert - nextAlert; 221 return currentAlert - nextAlert;
@@ -212,7 +232,25 @@ namespace OpenSim.Region.CoreModules.World.Region
212 232
213 private void OnTimer(object source, ElapsedEventArgs e) 233 private void OnTimer(object source, ElapsedEventArgs e)
214 { 234 {
215 int nextInterval = DoOneNotice(); 235 int nextInterval = DoOneNotice(true);
236
237 SetTimer(nextInterval);
238 }
239
240 public void DelayRestart(int seconds, string message)
241 {
242 if (m_CountdownTimer == null)
243 return;
244
245 m_CountdownTimer.Stop();
246 m_CountdownTimer = null;
247
248 m_Alerts = new List<int>(m_CurrentAlerts);
249 m_Alerts.Add(seconds);
250 m_Alerts.Sort();
251 m_Alerts.Reverse();
252
253 int nextInterval = DoOneNotice(false);
216 254
217 SetTimer(nextInterval); 255 SetTimer(nextInterval);
218 } 256 }
@@ -226,6 +264,9 @@ namespace OpenSim.Region.CoreModules.World.Region
226 if (m_DialogModule != null && message != String.Empty) 264 if (m_DialogModule != null && message != String.Empty)
227 m_DialogModule.SendGeneralAlert(message); 265 m_DialogModule.SendGeneralAlert(message);
228 } 266 }
267 if (m_MarkerPath != String.Empty)
268 File.Delete(Path.Combine(m_MarkerPath,
269 m_Scene.RegionInfo.RegionID.ToString()));
229 } 270 }
230 271
231 private void HandleRegionRestart(string module, string[] args) 272 private void HandleRegionRestart(string module, string[] args)
@@ -270,5 +311,25 @@ namespace OpenSim.Region.CoreModules.World.Region
270 311
271 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 312 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
272 } 313 }
314
315 protected void CreateMarkerFile()
316 {
317 if (m_MarkerPath == String.Empty)
318 return;
319
320 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
321 try
322 {
323 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
324 FileStream fs = File.Create(path);
325 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
326 Byte[] buf = enc.GetBytes(pidstring);
327 fs.Write(buf, 0, buf.Length);
328 fs.Close();
329 }
330 catch (Exception)
331 {
332 }
333 }
273 } 334 }
274} \ No newline at end of file 335} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index fd30c46..4d738a5 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -644,6 +644,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
644 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); 644 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
645 m_scene.SaveTerrain(); 645 m_scene.SaveTerrain();
646 646
647 m_scene.EventManager.TriggerTerrainUpdate();
648
647 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. 649 // Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
648 //m_scene.CreateTerrainTexture(true); 650 //m_scene.CreateTerrainTexture(true);
649 } 651 }
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index ed2b06a..d38f34b 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -65,6 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
65 private bool m_useAntiAliasing = false; // TODO: Make this a config option 65 private bool m_useAntiAliasing = false; // TODO: Make this a config option
66 private bool m_Enabled = false; 66 private bool m_Enabled = false;
67 67
68 private Bitmap lastImage = null;
69 private DateTime lastImageTime = DateTime.MinValue;
70
68 #region Region Module interface 71 #region Region Module interface
69 72
70 public void Initialise(IConfigSource source) 73 public void Initialise(IConfigSource source)
@@ -87,14 +90,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
87 90
88 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 91 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
89 if (renderers.Count > 0) 92 if (renderers.Count > 0)
90 { 93 m_log.Info("[MAPTILE]: Loaded prim mesher " + renderers[0]);
91 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
92 m_log.DebugFormat("[WARP 3D IMAGE MODULE]: Loaded prim mesher {0}", m_primMesher);
93 }
94 else 94 else
95 { 95 m_log.Info("[MAPTILE]: No prim mesher loaded, prim rendering will be disabled");
96 m_log.Debug("[WARP 3D IMAGE MODULE]: No prim mesher loaded, prim rendering will be disabled");
97 }
98 96
99 m_scene.RegisterModuleInterface<IMapImageGenerator>(this); 97 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
100 } 98 }
@@ -127,9 +125,25 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
127 125
128 public Bitmap CreateMapTile() 126 public Bitmap CreateMapTile()
129 { 127 {
128 if ((DateTime.Now - lastImageTime).TotalSeconds < 3600)
129 {
130 return lastImage.Clone(new Rectangle(0, 0, 256, 256), lastImage.PixelFormat);
131 }
132
133 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
134 if (renderers.Count > 0)
135 {
136 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
137 }
138
130 Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 139 Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f);
131 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)Constants.RegionSize, (int)Constants.RegionSize, (float)Constants.RegionSize, (float)Constants.RegionSize); 140 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)Constants.RegionSize, (int)Constants.RegionSize, (float)Constants.RegionSize, (float)Constants.RegionSize);
132 return CreateMapTile(viewport, false); 141 Bitmap tile = CreateMapTile(viewport, false);
142 m_primMesher = null;
143
144 lastImage = tile;
145 lastImageTime = DateTime.Now;
146 return lastImage.Clone(new Rectangle(0, 0, 256, 256), lastImage.PixelFormat);
133 } 147 }
134 148
135 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 149 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 708a9a2..14deeb6 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -128,85 +128,93 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 128
129 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 129 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
130 { 130 {
131 List<MapBlockData> blocks = new List<MapBlockData>(); 131 Util.FireAndForget(x =>
132 MapBlockData data;
133 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
134 { 132 {
133 if (mapName.Length < 2)
134 {
135 remoteClient.SendAlertMessage("Use a search string with at least 2 characters");
136 return;
137 }
138
139 //m_log.DebugFormat("MAP NAME=({0})", mapName);
140
141 // Hack to get around the fact that ll V3 now drops the port from the
142 // map name. See https://jira.secondlife.com/browse/VWR-28570
143 //
144 // Caller, use this magic form instead:
145 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128
146 // or url encode if possible.
147 // the hacks we do with this viewer...
148 //
149 string mapNameOrig = mapName;
150 if (mapName.Contains("|"))
151 mapName = mapName.Replace('|', ':');
152 if (mapName.Contains("+"))
153 mapName = mapName.Replace('+', ' ');
154 if (mapName.Contains("!"))
155 mapName = mapName.Replace('!', '/');
156
157 // try to fetch from GridServer
158 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
159 // if (regionInfos.Count == 0)
160 // remoteClient.SendAlertMessage("Hyperlink could not be established.");
161
162 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
163 List<MapBlockData> blocks = new List<MapBlockData>();
164
165 MapBlockData data;
166 if (regionInfos.Count > 0)
167 {
168 foreach (GridRegion info in regionInfos)
169 {
170 data = new MapBlockData();
171 data.Agents = 0;
172 data.Access = info.Access;
173 if (flags == 2) // V2 sends this
174 data.MapImageId = UUID.Zero;
175 else
176 data.MapImageId = info.TerrainImage;
177 // ugh! V2-3 is very sensitive about the result being
178 // exactly the same as the requested name
179 if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+"))
180 data.Name = mapNameOrig;
181 else
182 data.Name = info.RegionName;
183 data.RegionFlags = 0; // TODO not used?
184 data.WaterHeight = 0; // not used
185 data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
186 data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
187 blocks.Add(data);
188 }
189 }
190
135 // final block, closing the search result 191 // final block, closing the search result
136 AddFinalBlock(blocks); 192 data = new MapBlockData();
193 data.Agents = 0;
194 data.Access = 255;
195 data.MapImageId = UUID.Zero;
196 data.Name = mapName;
197 data.RegionFlags = 0;
198 data.WaterHeight = 0; // not used
199 data.X = 0;
200 data.Y = 0;
201 blocks.Add(data);
137 202
138 // flags are agent flags sent from the viewer. 203 // flags are agent flags sent from the viewer.
139 // they have different values depending on different viewers, apparently 204 // they have different values depending on different viewers, apparently
140 remoteClient.SendMapBlock(blocks, flags); 205 remoteClient.SendMapBlock(blocks, flags);
141 remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
142 return;
143 }
144
145 206
146 //m_log.DebugFormat("MAP NAME=({0})", mapName); 207 // send extra user messages for V3
147 208 // because the UI is very confusing
148 // Hack to get around the fact that ll V3 now drops the port from the 209 // while we don't fix the hard-coded urls
149 // map name. See https://jira.secondlife.com/browse/VWR-28570 210 if (flags == 2)
150 //
151 // Caller, use this magic form instead:
152 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128
153 // or url encode if possible.
154 // the hacks we do with this viewer...
155 //
156 string mapNameOrig = mapName;
157 if (mapName.Contains("|"))
158 mapName = mapName.Replace('|', ':');
159 if (mapName.Contains("+"))
160 mapName = mapName.Replace('+', ' ');
161 if (mapName.Contains("!"))
162 mapName = mapName.Replace('!', '/');
163
164 // try to fetch from GridServer
165 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
166
167 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags);
168 if (regionInfos.Count > 0)
169 {
170 foreach (GridRegion info in regionInfos)
171 { 211 {
172 data = new MapBlockData(); 212 if (regionInfos.Count == 0)
173 data.Agents = 0; 213 remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
174 data.Access = info.Access; 214// else if (regionInfos.Count == 1)
175 if (flags == 2) // V2 sends this 215// remoteClient.SendAgentAlertMessage("Region found!", false);
176 data.MapImageId = UUID.Zero;
177 else
178 data.MapImageId = info.TerrainImage;
179 // ugh! V2-3 is very sensitive about the result being
180 // exactly the same as the requested name
181 if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+"))
182 data.Name = mapNameOrig;
183 else
184 data.Name = info.RegionName;
185 data.RegionFlags = 0; // TODO not used?
186 data.WaterHeight = 0; // not used
187 data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
188 data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
189 blocks.Add(data);
190 } 216 }
191 } 217 });
192
193 // final block, closing the search result
194 AddFinalBlock(blocks);
195
196 // flags are agent flags sent from the viewer.
197 // they have different values depending on different viewers, apparently
198 remoteClient.SendMapBlock(blocks, flags);
199
200 // send extra user messages for V3
201 // because the UI is very confusing
202 // while we don't fix the hard-coded urls
203 if (flags == 2)
204 {
205 if (regionInfos.Count == 0)
206 remoteClient.SendAlertMessage("No regions found with that name.");
207 else if (regionInfos.Count == 1)
208 remoteClient.SendAlertMessage("Region found!");
209 }
210 } 218 }
211 219
212 private void AddFinalBlock(List<MapBlockData> blocks) 220 private void AddFinalBlock(List<MapBlockData> blocks)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index a26a5f0..bf18616 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -66,7 +66,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
66 private static readonly UUID STOP_UUID = UUID.Random(); 66 private static readonly UUID STOP_UUID = UUID.Random();
67 private static readonly string m_mapLayerPath = "0001/"; 67 private static readonly string m_mapLayerPath = "0001/";
68 68
69 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>(); 69 private ManualResetEvent queueEvent = new ManualResetEvent(false);
70 private Queue<MapRequestState> requests = new Queue<MapRequestState>();
71
72 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
73 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
70 74
71 protected Scene m_scene; 75 protected Scene m_scene;
72 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 76 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
@@ -74,15 +78,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
74 private int blacklistTimeout = 10*60*1000; // 10 minutes 78 private int blacklistTimeout = 10*60*1000; // 10 minutes
75 private byte[] myMapImageJPEG; 79 private byte[] myMapImageJPEG;
76 protected volatile bool m_Enabled = false; 80 protected volatile bool m_Enabled = false;
77 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>();
78 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 81 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>();
79 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 82 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
80 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 83 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
81 private List<UUID> m_rootAgents = new List<UUID>(); 84 private List<UUID> m_rootAgents = new List<UUID>();
82 private volatile bool threadrunning = false; 85 private volatile bool threadrunning = false;
83 86
84 private IServiceThrottleModule m_ServiceThrottle;
85
86 //private int CacheRegionsDistance = 256; 87 //private int CacheRegionsDistance = 256;
87 88
88 #region INonSharedRegionModule Members 89 #region INonSharedRegionModule Members
@@ -93,7 +94,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
93 if (Util.GetConfigVarFromSections<string>( 94 if (Util.GetConfigVarFromSections<string>(
94 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 95 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
95 m_Enabled = true; 96 m_Enabled = true;
96 97
97 blacklistTimeout 98 blacklistTimeout
98 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000; 99 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
99 } 100 }
@@ -133,10 +134,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
133 134
134 public virtual void RegionLoaded (Scene scene) 135 public virtual void RegionLoaded (Scene scene)
135 { 136 {
136 if (!m_Enabled)
137 return;
138
139 m_ServiceThrottle = scene.RequestModuleInterface<IServiceThrottleModule>();
140 } 137 }
141 138
142 139
@@ -176,13 +173,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
176 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 173 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
177 m_scene.EventManager.OnRegionUp += OnRegionUp; 174 m_scene.EventManager.OnRegionUp += OnRegionUp;
178 175
179// StartThread(new object()); 176 StartThread(new object());
180 } 177 }
181 178
182 // this has to be called with a lock on m_scene 179 // this has to be called with a lock on m_scene
183 protected virtual void RemoveHandlers() 180 protected virtual void RemoveHandlers()
184 { 181 {
185// StopThread(); 182 StopThread();
186 183
187 m_scene.EventManager.OnRegionUp -= OnRegionUp; 184 m_scene.EventManager.OnRegionUp -= OnRegionUp;
188 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 185 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -240,54 +237,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
240 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 237 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
241 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 238 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
242 239
243 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 240 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
244 { 241 //{
245 ScenePresence avatarPresence = null; 242 // ScenePresence avatarPresence = null;
246 243
247 m_scene.TryGetScenePresence(agentID, out avatarPresence); 244 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
248 245
249 if (avatarPresence != null) 246 // if (avatarPresence != null)
250 { 247 // {
251 bool lookup = false; 248 // bool lookup = false;
252 249
253 lock (cachedMapBlocks) 250 // lock (cachedMapBlocks)
254 { 251 // {
255 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 252 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
256 { 253 // {
257 List<MapBlockData> mapBlocks; 254 // List<MapBlockData> mapBlocks;
258 255
259 mapBlocks = cachedMapBlocks; 256 // mapBlocks = cachedMapBlocks;
260 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 257 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
261 } 258 // }
262 else 259 // else
263 { 260 // {
264 lookup = true; 261 // lookup = true;
265 } 262 // }
266 } 263 // }
267 if (lookup) 264 // if (lookup)
268 { 265 // {
269 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 266 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
270 267
271 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 268 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
272 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, 269 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
273 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, 270 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
274 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, 271 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
275 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); 272 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
276 foreach (GridRegion r in regions) 273 // foreach (GridRegion r in regions)
277 { 274 // {
278 MapBlockData block = new MapBlockData(); 275 // MapBlockData block = new MapBlockData();
279 MapBlockFromGridRegion(block, r, 0); 276 // MapBlockFromGridRegion(block, r, 0);
280 mapBlocks.Add(block); 277 // mapBlocks.Add(block);
281 } 278 // }
282 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 279 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
283 280
284 lock (cachedMapBlocks) 281 // lock (cachedMapBlocks)
285 cachedMapBlocks = mapBlocks; 282 // cachedMapBlocks = mapBlocks;
286 283
287 cachedTime = Util.UnixTimeSinceEpoch(); 284 // cachedTime = Util.UnixTimeSinceEpoch();
288 } 285 // }
289 } 286 // }
290 } 287 //}
291 288
292 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 289 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
293 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 290 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -314,8 +311,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
314 protected static OSDMapLayer GetOSDMapLayerResponse() 311 protected static OSDMapLayer GetOSDMapLayerResponse()
315 { 312 {
316 OSDMapLayer mapLayer = new OSDMapLayer(); 313 OSDMapLayer mapLayer = new OSDMapLayer();
317 mapLayer.Right = 5000; 314 mapLayer.Right = 2048;
318 mapLayer.Top = 5000; 315 mapLayer.Top = 2048;
319 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 316 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
320 317
321 return mapLayer; 318 return mapLayer;
@@ -344,6 +341,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
344 { 341 {
345 m_rootAgents.Remove(AgentId); 342 m_rootAgents.Remove(AgentId);
346 } 343 }
344 lock (m_mapBlockRequestEvent)
345 {
346 if (m_mapBlockRequests.ContainsKey(AgentId))
347 m_mapBlockRequests.Remove(AgentId);
348 }
347 } 349 }
348 #endregion 350 #endregion
349 351
@@ -366,6 +368,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
366 ThreadPriority.BelowNormal, 368 ThreadPriority.BelowNormal,
367 true, 369 true,
368 true); 370 true);
371 Watchdog.StartThread(
372 MapBlockSendThread,
373 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
374 ThreadPriority.BelowNormal,
375 true,
376 true);
369 } 377 }
370 378
371 /// <summary> 379 /// <summary>
@@ -381,7 +389,27 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
381 st.itemtype=0; 389 st.itemtype=0;
382 st.regionhandle=0; 390 st.regionhandle=0;
383 391
384 requests.Enqueue(st); 392 lock (requests)
393 {
394 queueEvent.Set();
395 requests.Enqueue(st);
396 }
397
398 MapBlockRequestData req = new MapBlockRequestData();
399
400 req.client = null;
401 req.minX = 0;
402 req.maxX = 0;
403 req.minY = 0;
404 req.maxY = 0;
405 req.flags = 0;
406
407 lock (m_mapBlockRequestEvent)
408 {
409 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
410 m_mapBlockRequests[UUID.Zero].Enqueue(req);
411 m_mapBlockRequestEvent.Set();
412 }
385 } 413 }
386 414
387 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 415 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -532,12 +560,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
532 /// </summary> 560 /// </summary>
533 public void process() 561 public void process()
534 { 562 {
535 //const int MAX_ASYNC_REQUESTS = 20; 563 const int MAX_ASYNC_REQUESTS = 20;
536 try 564 try
537 { 565 {
538 while (true) 566 while (true)
539 { 567 {
540 MapRequestState st = requests.Dequeue(1000); 568 MapRequestState st = new MapRequestState();
569 bool valid = false;
570 queueEvent.WaitOne();
571 lock (requests)
572 {
573 if (requests.Count > 0)
574 {
575 st = requests.Dequeue();
576 valid = true;
577 }
578 if (requests.Count == 0)
579 queueEvent.Reset();
580 }
581 if (!valid)
582 continue;
541 583
542 // end gracefully 584 // end gracefully
543 if (st.agentID == STOP_UUID) 585 if (st.agentID == STOP_UUID)
@@ -555,13 +597,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
555 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 597 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
556 { 598 {
557 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 599 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
558 Thread.Sleep(80); 600 Thread.Sleep(100);
559 601
560 RequestMapItemsDelegate d = RequestMapItemsAsync;
561 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
562 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
563 //RequestMapItemsCompleted(response);
564 Interlocked.Increment(ref nAsyncRequests); 602 Interlocked.Increment(ref nAsyncRequests);
603 Util.FireAndForget(x =>
604 {
605 RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
606 });
565 } 607 }
566 } 608 }
567 609
@@ -577,147 +619,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
577 Watchdog.RemoveThread(); 619 Watchdog.RemoveThread();
578 } 620 }
579 621
580 const int MAX_ASYNC_REQUESTS = 20;
581
582 /// <summary> 622 /// <summary>
583 /// Enqueues the map item request into the services throttle processing thread 623 /// Enqueues the map item request into the processing thread
584 /// </summary> 624 /// </summary>
585 /// <param name="state"></param> 625 /// <param name="state"></param>
586 public void EnqueueMapItemRequest(MapRequestState st) 626 public void EnqueueMapItemRequest(MapRequestState state)
587 {
588
589 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate
590 {
591 if (st.agentID != UUID.Zero)
592 {
593 bool dorequest = true;
594 lock (m_rootAgents)
595 {
596 if (!m_rootAgents.Contains(st.agentID))
597 dorequest = false;
598 }
599
600 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
601 {
602 if (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
603 {
604 // AH!!! Recursive !
605 // Put this request back in the queue and return
606 EnqueueMapItemRequest(st);
607 return;
608 }
609
610 RequestMapItemsDelegate d = RequestMapItemsAsync;
611 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
612 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
613 //RequestMapItemsCompleted(response);
614 Interlocked.Increment(ref nAsyncRequests);
615 }
616 }
617 });
618 }
619
620 /// <summary>
621 /// Sends the mapitem response to the IClientAPI
622 /// </summary>
623 /// <param name="response">The OSDMap Response for the mapitem</param>
624 private void RequestMapItemsCompleted(IAsyncResult iar)
625 { 627 {
626 AsyncResult result = (AsyncResult)iar; 628 lock (requests)
627 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
628
629 OSDMap response = (OSDMap)icon.EndInvoke(iar);
630
631 Interlocked.Decrement(ref nAsyncRequests);
632
633 if (!response.ContainsKey("requestID"))
634 return;
635
636 UUID requestID = response["requestID"].AsUUID();
637
638 if (requestID != UUID.Zero)
639 { 629 {
640 MapRequestState mrs = new MapRequestState(); 630 queueEvent.Set();
641 mrs.agentID = UUID.Zero; 631 requests.Enqueue(state);
642 lock (m_openRequests)
643 {
644 if (m_openRequests.ContainsKey(requestID))
645 {
646 mrs = m_openRequests[requestID];
647 m_openRequests.Remove(requestID);
648 }
649 }
650
651 if (mrs.agentID != UUID.Zero)
652 {
653 ScenePresence av = null;
654 m_scene.TryGetScenePresence(mrs.agentID, out av);
655 if (av != null)
656 {
657 if (response.ContainsKey(mrs.itemtype.ToString()))
658 {
659 List<mapItemReply> returnitems = new List<mapItemReply>();
660 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()];
661 for (int i = 0; i < itemarray.Count; i++)
662 {
663 OSDMap mapitem = (OSDMap)itemarray[i];
664 mapItemReply mi = new mapItemReply();
665 mi.x = (uint)mapitem["X"].AsInteger();
666 mi.y = (uint)mapitem["Y"].AsInteger();
667 mi.id = mapitem["ID"].AsUUID();
668 mi.Extra = mapitem["Extra"].AsInteger();
669 mi.Extra2 = mapitem["Extra2"].AsInteger();
670 mi.name = mapitem["Name"].AsString();
671 returnitems.Add(mi);
672 }
673 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
674 }
675
676 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
677 uint itemtype = 7;
678
679 if (response.ContainsKey(itemtype.ToString()))
680 {
681 List<mapItemReply> returnitems = new List<mapItemReply>();
682 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
683 for (int i = 0; i < itemarray.Count; i++)
684 {
685 OSDMap mapitem = (OSDMap)itemarray[i];
686 mapItemReply mi = new mapItemReply();
687 mi.x = (uint)mapitem["X"].AsInteger();
688 mi.y = (uint)mapitem["Y"].AsInteger();
689 mi.id = mapitem["ID"].AsUUID();
690 mi.Extra = mapitem["Extra"].AsInteger();
691 mi.Extra2 = mapitem["Extra2"].AsInteger();
692 mi.name = mapitem["Name"].AsString();
693 returnitems.Add(mi);
694 }
695 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
696 }
697
698 // Service 1 (MAP_ITEM_TELEHUB)
699 itemtype = 1;
700
701 if (response.ContainsKey(itemtype.ToString()))
702 {
703 List<mapItemReply> returnitems = new List<mapItemReply>();
704 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
705 for (int i = 0; i < itemarray.Count; i++)
706 {
707 OSDMap mapitem = (OSDMap)itemarray[i];
708 mapItemReply mi = new mapItemReply();
709 mi.x = (uint)mapitem["X"].AsInteger();
710 mi.y = (uint)mapitem["Y"].AsInteger();
711 mi.id = mapitem["ID"].AsUUID();
712 mi.Extra = mapitem["Extra"].AsInteger();
713 mi.Extra2 = mapitem["Extra2"].AsInteger();
714 mi.name = mapitem["Name"].AsString();
715 returnitems.Add(mi);
716 }
717 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
718 }
719 }
720 }
721 } 632 }
722 } 633 }
723 634
@@ -744,8 +655,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
744 EnqueueMapItemRequest(st); 655 EnqueueMapItemRequest(st);
745 } 656 }
746 657
747 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags,
748 uint EstateID, bool godlike, uint itemtype, ulong regionhandle);
749 /// <summary> 658 /// <summary>
750 /// Does the actual remote mapitem request 659 /// Does the actual remote mapitem request
751 /// This should be called from an asynchronous thread 660 /// This should be called from an asynchronous thread
@@ -760,7 +669,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
760 /// <param name="itemtype">passed in from packet</param> 669 /// <param name="itemtype">passed in from packet</param>
761 /// <param name="regionhandle">Region we're looking up</param> 670 /// <param name="regionhandle">Region we're looking up</param>
762 /// <returns></returns> 671 /// <returns></returns>
763 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 672 private void RequestMapItemsAsync(UUID id, uint flags,
764 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 673 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
765 { 674 {
766// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 675// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
@@ -783,7 +692,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
783 } 692 }
784 693
785 if (blacklisted) 694 if (blacklisted)
786 return new OSDMap(); 695 {
696 Interlocked.Decrement(ref nAsyncRequests);
697 return;
698 }
787 699
788 UUID requestID = UUID.Random(); 700 UUID requestID = UUID.Random();
789 lock (m_cachedRegionMapItemsAddress) 701 lock (m_cachedRegionMapItemsAddress)
@@ -791,6 +703,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
791 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 703 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
792 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 704 httpserver = m_cachedRegionMapItemsAddress[regionhandle];
793 } 705 }
706
794 if (httpserver.Length == 0) 707 if (httpserver.Length == 0)
795 { 708 {
796 uint x = 0, y = 0; 709 uint x = 0, y = 0;
@@ -835,18 +748,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
835 748
836 // Can't find the http server 749 // Can't find the http server
837 if (httpserver.Length == 0 || blacklisted) 750 if (httpserver.Length == 0 || blacklisted)
838 return new OSDMap(); 751 {
839 752 Interlocked.Decrement(ref nAsyncRequests);
840 MapRequestState mrs = new MapRequestState(); 753 return;
841 mrs.agentID = id; 754 }
842 mrs.EstateID = EstateID;
843 mrs.flags = flags;
844 mrs.godlike = godlike;
845 mrs.itemtype=itemtype;
846 mrs.regionhandle = regionhandle;
847
848 lock (m_openRequests)
849 m_openRequests.Add(requestID, mrs);
850 755
851 WebRequest mapitemsrequest = null; 756 WebRequest mapitemsrequest = null;
852 try 757 try
@@ -856,7 +761,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
856 catch (Exception e) 761 catch (Exception e)
857 { 762 {
858 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 763 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
859 return new OSDMap(); 764 Interlocked.Decrement(ref nAsyncRequests);
765 return;
860 } 766 }
861 767
862 mapitemsrequest.Method = "POST"; 768 mapitemsrequest.Method = "POST";
@@ -881,7 +787,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
881 catch (WebException ex) 787 catch (WebException ex)
882 { 788 {
883 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 789 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
884 responseMap["connect"] = OSD.FromBoolean(false);
885 lock (m_blacklistedurls) 790 lock (m_blacklistedurls)
886 { 791 {
887 if (!m_blacklistedurls.ContainsKey(httpserver)) 792 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -890,13 +795,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
890 795
891 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 796 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
892 797
893 return responseMap; 798 Interlocked.Decrement(ref nAsyncRequests);
799 return;
894 } 800 }
895 catch 801 catch
896 { 802 {
897 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 803 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
898 responseMap["connect"] = OSD.FromBoolean(false); 804 Interlocked.Decrement(ref nAsyncRequests);
899 return responseMap; 805 return;
900 } 806 }
901 finally 807 finally
902 { 808 {
@@ -905,26 +811,24 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
905 } 811 }
906 812
907 string response_mapItems_reply = null; 813 string response_mapItems_reply = null;
908 { 814 { // get the response
815 StreamReader sr = null;
909 try 816 try
910 { 817 {
911 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 818 WebResponse webResponse = mapitemsrequest.GetResponse();
819 if (webResponse != null)
912 { 820 {
913 if (webResponse != null) 821 sr = new StreamReader(webResponse.GetResponseStream());
914 { 822 response_mapItems_reply = sr.ReadToEnd().Trim();
915 using (Stream s = webResponse.GetResponseStream()) 823 }
916 using (StreamReader sr = new StreamReader(s)) 824 else
917 response_mapItems_reply = sr.ReadToEnd().Trim(); 825 {
918 } 826 Interlocked.Decrement(ref nAsyncRequests);
919 else 827 return;
920 { 828 }
921 return new OSDMap();
922 }
923 }
924 } 829 }
925 catch (WebException) 830 catch (WebException)
926 { 831 {
927 responseMap["connect"] = OSD.FromBoolean(false);
928 lock (m_blacklistedurls) 832 lock (m_blacklistedurls)
929 { 833 {
930 if (!m_blacklistedurls.ContainsKey(httpserver)) 834 if (!m_blacklistedurls.ContainsKey(httpserver))
@@ -933,19 +837,25 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
933 837
934 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 838 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
935 839
936 return responseMap; 840 Interlocked.Decrement(ref nAsyncRequests);
841 return;
937 } 842 }
938 catch 843 catch
939 { 844 {
940 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 845 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
941 responseMap["connect"] = OSD.FromBoolean(false);
942 lock (m_blacklistedregions) 846 lock (m_blacklistedregions)
943 { 847 {
944 if (!m_blacklistedregions.ContainsKey(regionhandle)) 848 if (!m_blacklistedregions.ContainsKey(regionhandle))
945 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 849 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
946 } 850 }
947 851
948 return responseMap; 852 Interlocked.Decrement(ref nAsyncRequests);
853 return;
854 }
855 finally
856 {
857 if (sr != null)
858 sr.Close();
949 } 859 }
950 860
951 OSD rezResponse = null; 861 OSD rezResponse = null;
@@ -959,15 +869,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
959 catch (Exception ex) 869 catch (Exception ex)
960 { 870 {
961 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 871 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
962 responseMap["connect"] = OSD.FromBoolean(false);
963
964 lock (m_blacklistedregions) 872 lock (m_blacklistedregions)
965 { 873 {
966 if (!m_blacklistedregions.ContainsKey(regionhandle)) 874 if (!m_blacklistedregions.ContainsKey(regionhandle))
967 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 875 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
968 } 876 }
969 877
970 return responseMap; 878 Interlocked.Decrement(ref nAsyncRequests);
879 return;
971 } 880 }
972 } 881 }
973 882
@@ -981,7 +890,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
981 } 890 }
982 } 891 }
983 892
984 return responseMap; 893 Interlocked.Decrement(ref nAsyncRequests);
894
895 if (id != UUID.Zero)
896 {
897 ScenePresence av = null;
898 m_scene.TryGetScenePresence(id, out av);
899 if (av != null)
900 {
901 if (responseMap.ContainsKey(itemtype.ToString()))
902 {
903 List<mapItemReply> returnitems = new List<mapItemReply>();
904 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
905 for (int i = 0; i < itemarray.Count; i++)
906 {
907 OSDMap mapitem = (OSDMap)itemarray[i];
908 mapItemReply mi = new mapItemReply();
909 mi.x = (uint)mapitem["X"].AsInteger();
910 mi.y = (uint)mapitem["Y"].AsInteger();
911 mi.id = mapitem["ID"].AsUUID();
912 mi.Extra = mapitem["Extra"].AsInteger();
913 mi.Extra2 = mapitem["Extra2"].AsInteger();
914 mi.name = mapitem["Name"].AsString();
915 returnitems.Add(mi);
916 }
917 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
918 }
919
920 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
921 itemtype = 7;
922
923 if (responseMap.ContainsKey(itemtype.ToString()))
924 {
925 List<mapItemReply> returnitems = new List<mapItemReply>();
926 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
927 for (int i = 0; i < itemarray.Count; i++)
928 {
929 OSDMap mapitem = (OSDMap)itemarray[i];
930 mapItemReply mi = new mapItemReply();
931 mi.x = (uint)mapitem["X"].AsInteger();
932 mi.y = (uint)mapitem["Y"].AsInteger();
933 mi.id = mapitem["ID"].AsUUID();
934 mi.Extra = mapitem["Extra"].AsInteger();
935 mi.Extra2 = mapitem["Extra2"].AsInteger();
936 mi.name = mapitem["Name"].AsString();
937 returnitems.Add(mi);
938 }
939 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
940 }
941
942 // Service 1 (MAP_ITEM_TELEHUB)
943 itemtype = 1;
944
945 if (responseMap.ContainsKey(itemtype.ToString()))
946 {
947 List<mapItemReply> returnitems = new List<mapItemReply>();
948 OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
949 for (int i = 0; i < itemarray.Count; i++)
950 {
951 OSDMap mapitem = (OSDMap)itemarray[i];
952 mapItemReply mi = new mapItemReply();
953 mi.x = (uint)mapitem["X"].AsInteger();
954 mi.y = (uint)mapitem["Y"].AsInteger();
955 mi.id = mapitem["ID"].AsUUID();
956 mi.Extra = mapitem["Extra"].AsInteger();
957 mi.Extra2 = mapitem["Extra2"].AsInteger();
958 mi.name = mapitem["Name"].AsString();
959 returnitems.Add(mi);
960 }
961 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
962 }
963 }
964 }
985 } 965 }
986 966
987 /// <summary> 967 /// <summary>
@@ -991,7 +971,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
991 /// <param name="minY"></param> 971 /// <param name="minY"></param>
992 /// <param name="maxX"></param> 972 /// <param name="maxX"></param>
993 /// <param name="maxY"></param> 973 /// <param name="maxY"></param>
994 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 974 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
995 { 975 {
996 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); 976 //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
997 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 977 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
@@ -1044,21 +1024,91 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1044 1024
1045 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1025 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1046 { 1026 {
1027 MapBlockRequestData req = new MapBlockRequestData();
1028
1029 req.client = remoteClient;
1030 req.minX = minX;
1031 req.maxX = maxX;
1032 req.minY = minY;
1033 req.maxY = maxY;
1034 req.flags = flag;
1035
1036 lock (m_mapBlockRequestEvent)
1037 {
1038 if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
1039 m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
1040 m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
1041 m_mapBlockRequestEvent.Set();
1042 }
1043
1044 return new List<MapBlockData>();
1045 }
1046
1047 protected void MapBlockSendThread()
1048 {
1049 while (true)
1050 {
1051 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1052
1053 m_mapBlockRequestEvent.WaitOne();
1054 lock (m_mapBlockRequestEvent)
1055 {
1056 int total = 0;
1057 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1058 {
1059 if (q.Count > 0)
1060 thisRunData.Add(q.Dequeue());
1061
1062 total += q.Count;
1063 }
1064
1065 if (total == 0)
1066 m_mapBlockRequestEvent.Reset();
1067 }
1068
1069 foreach (MapBlockRequestData req in thisRunData)
1070 {
1071 // Null client stops thread
1072 if (req.client == null)
1073 return;
1074
1075 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1076 }
1077
1078 Thread.Sleep(50);
1079 }
1080 }
1081
1082 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1083 {
1084 List<MapBlockData> allBlocks = new List<MapBlockData>();
1047 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1085 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1048 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1086 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1049 (minX - 4) * (int)Constants.RegionSize, 1087 minX * (int)Constants.RegionSize,
1050 (maxX + 4) * (int)Constants.RegionSize, 1088 maxX * (int)Constants.RegionSize,
1051 (minY - 4) * (int)Constants.RegionSize, 1089 minY * (int)Constants.RegionSize,
1052 (maxY + 4) * (int)Constants.RegionSize); 1090 maxY * (int)Constants.RegionSize);
1091// (minX - 4) * (int)Constants.RegionSize,
1092// (maxX + 4) * (int)Constants.RegionSize,
1093// (minY - 4) * (int)Constants.RegionSize,
1094// (maxY + 4) * (int)Constants.RegionSize);
1053 foreach (GridRegion r in regions) 1095 foreach (GridRegion r in regions)
1054 { 1096 {
1055 MapBlockData block = new MapBlockData(); 1097 MapBlockData block = new MapBlockData();
1056 MapBlockFromGridRegion(block, r, flag); 1098 MapBlockFromGridRegion(block, r, flag);
1057 mapBlocks.Add(block); 1099 mapBlocks.Add(block);
1100 allBlocks.Add(block);
1101 if (mapBlocks.Count >= 10)
1102 {
1103 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1104 mapBlocks.Clear();
1105 Thread.Sleep(50);
1106 }
1058 } 1107 }
1059 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1108 if (mapBlocks.Count > 0)
1109 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1060 1110
1061 return mapBlocks; 1111 return allBlocks;
1062 } 1112 }
1063 1113
1064 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) 1114 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
@@ -1282,7 +1332,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1282 } 1332 }
1283 else 1333 else
1284 { 1334 {
1285 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1335 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1286 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1336 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1287 { 1337 {
1288 OSDMap responsemapdata = new OSDMap(); 1338 OSDMap responsemapdata = new OSDMap();
@@ -1458,6 +1508,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1458 { 1508 {
1459 m_rootAgents.Remove(avatar.UUID); 1509 m_rootAgents.Remove(avatar.UUID);
1460 } 1510 }
1511
1512 lock (m_mapBlockRequestEvent)
1513 {
1514 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1515 m_mapBlockRequests.Remove(avatar.UUID);
1516 }
1461 } 1517 }
1462 1518
1463 public void OnRegionUp(GridRegion otherRegion) 1519 public void OnRegionUp(GridRegion otherRegion)
@@ -1502,9 +1558,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1502 Color background = Color.FromArgb(0, 0, 0, 0); 1558 Color background = Color.FromArgb(0, 0, 0, 0);
1503 SolidBrush transparent = new SolidBrush(background); 1559 SolidBrush transparent = new SolidBrush(background);
1504 Graphics g = Graphics.FromImage(overlay); 1560 Graphics g = Graphics.FromImage(overlay);
1505 g.FillRectangle(transparent, 0, 0, 256, 256); 1561 g.FillRectangle(transparent, 0, 0, 255, 255);
1506 1562
1507 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1563 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9));
1564 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1508 1565
1509 foreach (ILandObject land in parcels) 1566 foreach (ILandObject land in parcels)
1510 { 1567 {
@@ -1512,8 +1569,42 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1512 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0) 1569 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1513 { 1570 {
1514 landForSale = true; 1571 landForSale = true;
1572
1573 bool[,] landBitmap = land.GetLandBitmap();
1574
1575 for (int x = 0 ; x < 64 ; x++)
1576 {
1577 for (int y = 0 ; y < 64 ; y++)
1578 {
1579 if (landBitmap[x, y])
1580 {
1581 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1582
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 }
1604 }
1605 }
1515 1606
1516 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); 1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1517 } 1608 }
1518 } 1609 }
1519 1610
@@ -1525,15 +1616,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1525 1616
1526 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName); 1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1527 1618
1528 for (int x = 0 ; x < 64 ; x++)
1529 {
1530 for (int y = 0 ; y < 64 ; y++)
1531 {
1532 if (saleBitmap[x, y])
1533 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1534 }
1535 }
1536
1537 try 1619 try
1538 { 1620 {
1539 return OpenJPEG.EncodeFromImage(overlay, true); 1621 return OpenJPEG.EncodeFromImage(overlay, true);
@@ -1555,4 +1637,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1555 public uint itemtype; 1637 public uint itemtype;
1556 public ulong regionhandle; 1638 public ulong regionhandle;
1557 } 1639 }
1640
1641 public struct MapBlockRequestData
1642 {
1643 public IClientAPI client;
1644 public int minX;
1645 public int minY;
1646 public int maxX;
1647 public int maxY;
1648 public uint flags;
1649 }
1558} 1650}