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.cs28
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs239
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs194
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs399
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs78
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs235
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs87
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs247
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs109
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs181
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs178
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs104
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs1011
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs285
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs96
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs225
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs439
-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.cs81
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs29
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs34
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs13
-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.cs40
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs32
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs767
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs215
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs127
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs176
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs69
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs29
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs633
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs54
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs119
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs1488
91 files changed, 5403 insertions, 3246 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index f56d17d..1a19585 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
152 } 152 }
153 } 153 }
154 154
155 public void RequestCreateInventoryItem(IClientAPI remoteClient, 155 public bool RequestCreateInventoryItem(IClientAPI remoteClient,
156 UUID transactionID, UUID folderID, uint callbackID, 156 UUID transactionID, UUID folderID, uint callbackID,
157 string description, string name, sbyte invType, 157 string description, string name, sbyte invType,
158 sbyte type, byte wearableType, uint nextOwnerMask) 158 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -162,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
162 uploader.RequestCreateInventoryItem( 162 uploader.RequestCreateInventoryItem(
163 remoteClient, folderID, callbackID, 163 remoteClient, folderID, callbackID,
164 description, name, invType, type, wearableType, nextOwnerMask); 164 description, name, invType, type, wearableType, nextOwnerMask);
165
166 return true;
165 } 167 }
166 168
167 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 169 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
@@ -170,6 +172,17 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
170 { 172 {
171 AssetXferUploader uploader = RequestXferUploader(transactionID); 173 AssetXferUploader uploader = RequestXferUploader(transactionID);
172 174
175 // Here we need to get the old asset to extract the
176 // texture UUIDs if it's a wearable.
177 if (item.Type == (int)AssetType.Bodypart ||
178 item.Type == (int)AssetType.Clothing ||
179 item.Type == (int)CustomAssetType.AnimationSet)
180 {
181 AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
182 if (oldAsset != null)
183 uploader.SetOldData(oldAsset.Data);
184 }
185
173 uploader.RequestUpdateTaskInventoryItem(remoteClient, item); 186 uploader.RequestUpdateTaskInventoryItem(remoteClient, item);
174 } 187 }
175 188
@@ -178,7 +191,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
178 { 191 {
179 AssetXferUploader uploader = RequestXferUploader(transactionID); 192 AssetXferUploader uploader = RequestXferUploader(transactionID);
180 193
194 // Here we need to get the old asset to extract the
195 // texture UUIDs if it's a wearable.
196 if (item.AssetType == (int)AssetType.Bodypart ||
197 item.AssetType == (int)AssetType.Clothing ||
198 item.AssetType == (int)CustomAssetType.AnimationSet)
199 {
200 AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
201 if (oldAsset != null)
202 uploader.SetOldData(oldAsset.Data);
203 }
204
181 uploader.RequestUpdateInventoryItem(remoteClient, item); 205 uploader.RequestUpdateInventoryItem(remoteClient, item);
182 } 206 }
183 } 207 }
184} \ No newline at end of file 208}
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 5143204..c14e89f 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;
@@ -40,6 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40{ 41{
41 public class AssetXferUploader 42 public class AssetXferUploader
42 { 43 {
44 // Viewer's notion of the default texture
45 private List<UUID> defaultIDs = new List<UUID> {
46 new UUID("5748decc-f629-461c-9a36-a35a221fe21f"),
47 new UUID("7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"),
48 new UUID("6522e74d-1660-4e7f-b601-6f48c1659a77"),
49 new UUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97")
50 };
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 52
45 /// <summary> 53 /// <summary>
@@ -87,6 +95,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
87 95
88 private sbyte type = 0; 96 private sbyte type = 0;
89 private byte wearableType = 0; 97 private byte wearableType = 0;
98 private byte[] m_oldData = null;
90 public ulong XferID; 99 public ulong XferID;
91 private Scene m_Scene; 100 private Scene m_Scene;
92 101
@@ -129,18 +138,27 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
129 138
130 if (XferID == xferID) 139 if (XferID == xferID)
131 { 140 {
132 if (m_asset.Data.Length > 1) 141 lock (this)
133 { 142 {
134 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; 143 int assetLength = m_asset.Data.Length;
135 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); 144 int dataLength = data.Length;
136 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); 145
137 m_asset.Data = destinationArray; 146 if (m_asset.Data.Length > 1)
138 } 147 {
139 else 148 byte[] destinationArray = new byte[assetLength + dataLength];
140 { 149 Array.Copy(m_asset.Data, 0, destinationArray, 0, assetLength);
141 byte[] buffer2 = new byte[data.Length - 4]; 150 Array.Copy(data, 0, destinationArray, assetLength, dataLength);
142 Array.Copy(data, 4, buffer2, 0, data.Length - 4); 151 m_asset.Data = destinationArray;
143 m_asset.Data = buffer2; 152 }
153 else
154 {
155 if (dataLength > 4)
156 {
157 byte[] buffer2 = new byte[dataLength - 4];
158 Array.Copy(data, 4, buffer2, 0, dataLength - 4);
159 m_asset.Data = buffer2;
160 }
161 }
144 } 162 }
145 163
146 ourClient.SendConfirmXfer(xferID, packetID); 164 ourClient.SendConfirmXfer(xferID, packetID);
@@ -244,10 +262,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
244 { 262 {
245 CompleteTaskItemUpdate(m_updateTaskItemData); 263 CompleteTaskItemUpdate(m_updateTaskItemData);
246 } 264 }
247// else if (m_storeLocal) 265 else if (m_asset.Local)
248// { 266 {
249// m_Scene.AssetService.Store(m_asset); 267 m_Scene.AssetService.Store(m_asset);
250// } 268 }
251 } 269 }
252 270
253 m_log.DebugFormat( 271 m_log.DebugFormat(
@@ -319,14 +337,16 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
319 m_asset.Description = item.Description; 337 m_asset.Description = item.Description;
320 m_asset.Type = (sbyte)item.AssetType; 338 m_asset.Type = (sbyte)item.AssetType;
321 339
322 if (m_asset.FullID != UUID.Zero) 340 // remove redundante m_Scene.InventoryService.UpdateItem
323 { 341 // if uploadState == UploadState.Complete)
342// if (m_asset.FullID != UUID.Zero)
343// {
324 // We must always store the item at this point even if the asset hasn't finished uploading, in order 344 // We must always store the item at this point even if the asset hasn't finished uploading, in order
325 // to avoid a race condition when the appearance module retrieves the item to set the asset id in 345 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
326 // the AvatarAppearance structure. 346 // the AvatarAppearance structure.
327 item.AssetID = m_asset.FullID; 347// item.AssetID = m_asset.FullID;
328 m_Scene.InventoryService.UpdateItem(item); 348// m_Scene.InventoryService.UpdateItem(item);
329 } 349// }
330 350
331 if (m_uploadState == UploadState.Complete) 351 if (m_uploadState == UploadState.Complete)
332 { 352 {
@@ -334,10 +354,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
334 } 354 }
335 else 355 else
336 { 356 {
337// m_log.DebugFormat( 357 // do it here to avoid the eventual race condition
338// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}", 358 if (m_asset.FullID != UUID.Zero)
339// item.Name, remoteClient.Name, transactionID); 359 {
340 360 // We must always store the item at this point even if the asset hasn't finished uploading, in order
361 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
362 // the AvatarAppearance structure.
363 item.AssetID = m_asset.FullID;
364 m_Scene.InventoryService.UpdateItem(item);
365 }
366
367
368 // m_log.DebugFormat(
369 // "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
370 // item.Name, remoteClient.Name, transactionID);
371
341 m_updateItem = true; 372 m_updateItem = true;
342 m_updateItemData = item; 373 m_updateItemData = item;
343 } 374 }
@@ -376,7 +407,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
376// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 407// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
377// m_asset.FullID, item.Name, ourClient.Name); 408// m_asset.FullID, item.Name, ourClient.Name);
378 409
410 ValidateAssets();
379 m_Scene.AssetService.Store(m_asset); 411 m_Scene.AssetService.Store(m_asset);
412 if (m_asset.FullID != UUID.Zero)
413 {
414 item.AssetID = m_asset.FullID;
415 m_Scene.InventoryService.UpdateItem(item);
416 }
417
418 ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0);
380 419
381 m_transactions.RemoveXferUploader(m_transactionID); 420 m_transactions.RemoveXferUploader(m_transactionID);
382 421
@@ -393,6 +432,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
393// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", 432// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
394// m_asset.FullID, taskItem.Name, ourClient.Name); 433// m_asset.FullID, taskItem.Name, ourClient.Name);
395 434
435 ValidateAssets();
396 m_Scene.AssetService.Store(m_asset); 436 m_Scene.AssetService.Store(m_asset);
397 437
398 m_transactions.RemoveXferUploader(m_transactionID); 438 m_transactions.RemoveXferUploader(m_transactionID);
@@ -400,6 +440,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
400 440
401 private void CompleteCreateItem(uint callbackID) 441 private void CompleteCreateItem(uint callbackID)
402 { 442 {
443 ValidateAssets();
403 m_Scene.AssetService.Store(m_asset); 444 m_Scene.AssetService.Store(m_asset);
404 445
405 InventoryItemBase item = new InventoryItemBase(); 446 InventoryItemBase item = new InventoryItemBase();
@@ -420,13 +461,159 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
420 item.Flags = (uint) wearableType; 461 item.Flags = (uint) wearableType;
421 item.CreationDate = Util.UnixTimeSinceEpoch(); 462 item.CreationDate = Util.UnixTimeSinceEpoch();
422 463
464 m_log.DebugFormat("[XFER]: Created item {0} with asset {1}",
465 item.ID, item.AssetID);
466
423 if (m_Scene.AddInventoryItem(item)) 467 if (m_Scene.AddInventoryItem(item))
424 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 468 ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, callbackID);
425 else 469 else
426 ourClient.SendAlertMessage("Unable to create inventory item"); 470 ourClient.SendAlertMessage("Unable to create inventory item");
427 471
428 m_transactions.RemoveXferUploader(m_transactionID); 472 m_transactions.RemoveXferUploader(m_transactionID);
429 } 473 }
430 474
475
476 private void ValidateAssets()
477 {
478 if (m_asset.Type == (sbyte)CustomAssetType.AnimationSet)
479 {
480 AnimationSet animSet = new AnimationSet(m_asset.Data);
481
482 bool allOk = animSet.Validate(x => {
483 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
484 int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
485 if ((perms & required) != required)
486 return false;
487 return true;
488 });
489
490 if (!allOk)
491 m_asset.Data = animSet.ToBytes();
492 }
493
494 if (m_asset.Type == (sbyte)AssetType.Clothing ||
495 m_asset.Type == (sbyte)AssetType.Bodypart)
496 {
497 string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
498 string[] lines = content.Split(new char[] {'\n'});
499
500 List<string> validated = new List<string>();
501
502 Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
503
504 int textures = 0;
505
506 foreach (string line in lines)
507 {
508 try
509 {
510 if (line.StartsWith("textures "))
511 {
512 textures = Convert.ToInt32(line.Substring(9));
513 validated.Add(line);
514 }
515 else if (textures > 0)
516 {
517 string[] parts = line.Split(new char[] {' '});
518
519 UUID tx = new UUID(parts[1]);
520 int id = Convert.ToInt32(parts[0]);
521
522 if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
523 (allowed.ContainsKey(id) && allowed[id] == tx))
524 {
525 validated.Add(parts[0] + " " + tx.ToString());
526 }
527 else
528 {
529 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
530 int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
531
532 if ((perms & full) != full)
533 {
534 m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
535 validated.Add(parts[0] + " " + UUID.Zero.ToString());
536 }
537 else
538 {
539 validated.Add(line);
540 }
541 }
542 textures--;
543 }
544 else
545 {
546 validated.Add(line);
547 }
548 }
549 catch
550 {
551 // If it's malformed, skip it
552 }
553 }
554
555 string final = String.Join("\n", validated.ToArray());
556
557 m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
558 }
559 }
560
561 /// <summary>
562 /// Get the asset data uploaded in this transfer.
563 /// </summary>
564 /// <returns>null if the asset has not finished uploading</returns>
565 public AssetBase GetAssetData()
566 {
567 if (m_uploadState == UploadState.Complete)
568 {
569 ValidateAssets();
570 return m_asset;
571 }
572
573 return null;
574 }
575
576 public void SetOldData(byte[] d)
577 {
578 m_oldData = d;
579 }
580
581 private Dictionary<int,UUID> ExtractTexturesFromOldData()
582 {
583 Dictionary<int,UUID> result = new Dictionary<int,UUID>();
584 if (m_oldData == null)
585 return result;
586
587 string content = System.Text.Encoding.ASCII.GetString(m_oldData);
588 string[] lines = content.Split(new char[] {'\n'});
589
590 int textures = 0;
591
592 foreach (string line in lines)
593 {
594 try
595 {
596 if (line.StartsWith("textures "))
597 {
598 textures = Convert.ToInt32(line.Substring(9));
599 }
600 else if (textures > 0)
601 {
602 string[] parts = line.Split(new char[] {' '});
603
604 UUID tx = new UUID(parts[1]);
605 int id = Convert.ToInt32(parts[0]);
606 result[id] = tx;
607 textures--;
608 }
609 }
610 catch
611 {
612 // If it's malformed, skip it
613 }
614 }
615
616 return result;
617 }
431 } 618 }
432} \ No newline at end of file 619}
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/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7d9c9a9..c4abc99 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -594,6 +594,11 @@ namespace OpenSim.Region.CoreModules.Asset
594 dir, dirSize); 594 dir, dirSize);
595 } 595 }
596 } 596 }
597 catch (DirectoryNotFoundException)
598 {
599 // If we get here, another node on the same box has
600 // already removed the directory. Continue with next.
601 }
597 catch (Exception e) 602 catch (Exception e)
598 { 603 {
599 m_log.Warn( 604 m_log.Warn(
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2f67c4e..92beed2 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{
@@ -303,6 +304,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
303 if (DebugLevel > 0) 304 if (DebugLevel > 0)
304 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); 305 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
305 306
307 XmlDocument doc = new XmlDocument();
308 string stateData = String.Empty;
309
310 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
311 if (attServ != null)
312 {
313 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
314 stateData = attServ.Get(sp.UUID.ToString());
315 if (stateData != String.Empty)
316 {
317 try
318 {
319 doc.LoadXml(stateData);
320 }
321 catch { }
322 }
323 }
324
325 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
326
327 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
328 if (nodes.Count > 0)
329 {
330 foreach (XmlNode n in nodes)
331 {
332 XmlElement elem = (XmlElement)n;
333 string itemID = elem.GetAttribute("ItemID");
334 string xml = elem.InnerXml;
335
336 itemData[new UUID(itemID)] = xml;
337 }
338 }
339
340
306 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 341 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
307 342
308 // Let's get all items at once, so they get cached 343 // Let's get all items at once, so they get cached
@@ -330,10 +365,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
330 365
331 try 366 try
332 { 367 {
368 string xmlData;
369 XmlDocument d = null;
370 UUID asset;
371 if (itemData.TryGetValue(attach.ItemID, out xmlData))
372 {
373 d = new XmlDocument();
374 d.LoadXml(xmlData);
375 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
376 }
377
333 // If we're an NPC then skip all the item checks and manipulations since we don't have an 378 // If we're an NPC then skip all the item checks and manipulations since we don't have an
334 // inventory right now. 379 // inventory right now.
335 RezSingleAttachmentFromInventoryInternal( 380 RezSingleAttachmentFromInventoryInternal(
336 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); 381 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
337 } 382 }
338 catch (Exception e) 383 catch (Exception e)
339 { 384 {
@@ -361,27 +406,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 406
362 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); 407 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
363 408
364 foreach (SceneObjectGroup so in attachments)
365 {
366 // Scripts MUST be snapshotted before the object is
367 // removed from the scene because doing otherwise will
368 // clobber the run flag
369 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
370 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
371 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
372 409
373// m_log.DebugFormat( 410 if (sp.PresenceType != PresenceType.Npc)
374// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}",
375// so.Name, sp.Name, m_scene.Name, scriptStates[so]);
376 }
377
378 lock (sp.AttachmentsSyncLock)
379 { 411 {
380 foreach (SceneObjectGroup so in attachments) 412 foreach (SceneObjectGroup so in attachments)
381 UpdateDetachedObject(sp, so, scriptStates[so]); 413 {
382 414 // Scripts MUST be snapshotted before the object is
383 sp.ClearAttachments(); 415 // removed from the scene because doing otherwise will
416 // clobber the run flag
417 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
418 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
419 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
420 }
421
422 lock (sp.AttachmentsSyncLock)
423 {
424 foreach (SceneObjectGroup so in attachments)
425 UpdateDetachedObject(sp, so, scriptStates[so]);
426 sp.ClearAttachments();
427 }
384 } 428 }
429 else
430 {
431 lock (sp.AttachmentsSyncLock)
432 {
433 foreach (SceneObjectGroup so in attachments)
434 UpdateDetachedObject(sp, so, String.Empty);
435 sp.ClearAttachments();
436 }
437 }
385 } 438 }
386 439
387 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 440 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
@@ -402,20 +455,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
402 sp.ClearAttachments(); 455 sp.ClearAttachments();
403 } 456 }
404 457
405 public bool AttachObject( 458 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
406 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append)
407 { 459 {
408 if (!Enabled) 460 if (!Enabled)
409 return false; 461 return false;
410 462
411 group.DetachFromBackup(); 463 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
412
413 bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append);
414
415 if (!success)
416 group.AttachToBackup();
417
418 return success;
419 } 464 }
420 465
421 /// <summary> 466 /// <summary>
@@ -428,10 +473,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
428 /// <param name='silent'></param> 473 /// <param name='silent'></param>
429 /// <param name='addToInventory'>If true then add object to user inventory.</param> 474 /// <param name='addToInventory'>If true then add object to user inventory.</param>
430 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> 475 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
431 /// <param name='append'>Append to attachment point rather than replace.</param> 476 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
432 private bool AttachObjectInternal(
433 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append)
434 { 477 {
478// m_log.DebugFormat(
479// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
480// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
481
482 if (sp.GetAttachments().Contains(group))
483 {
484// m_log.WarnFormat(
485// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
486// group.Name, group.LocalId, sp.Name, AttachmentPt);
487
488 return false;
489 }
490
435 if (group.GetSittingAvatarsCount() != 0) 491 if (group.GetSittingAvatarsCount() != 0)
436 { 492 {
437 if (DebugLevel > 0) 493 if (DebugLevel > 0)
@@ -443,6 +499,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
443 } 499 }
444 500
445 Vector3 attachPos = group.AbsolutePosition; 501 Vector3 attachPos = group.AbsolutePosition;
502
503 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
504 // be removed when that functionality is implemented in opensim
505 attachmentPt &= 0x7f;
506
446 // If the attachment point isn't the same as the one previously used 507 // If the attachment point isn't the same as the one previously used
447 // set it's offset position = 0 so that it appears on the attachment point 508 // set it's offset position = 0 so that it appears on the attachment point
448 // and not in a weird location somewhere unknown. 509 // and not in a weird location somewhere unknown.
@@ -481,9 +542,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
481 attachPos = Vector3.Zero; 542 attachPos = Vector3.Zero;
482 } 543 }
483 544
484 group.AttachmentPoint = attachmentPt;
485 group.AbsolutePosition = attachPos;
486
487 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 545 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
488 546
489 if (attachments.Contains(group)) 547 if (attachments.Contains(group))
@@ -516,6 +574,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
516 574
517 lock (sp.AttachmentsSyncLock) 575 lock (sp.AttachmentsSyncLock)
518 { 576 {
577 group.AttachmentPoint = attachmentPt;
578 group.AbsolutePosition = attachPos;
579
519 if (addToInventory && sp.PresenceType != PresenceType.Npc) 580 if (addToInventory && sp.PresenceType != PresenceType.Npc)
520 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); 581 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
521 582
@@ -546,7 +607,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
546 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 607 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
547 } 608 }
548 609
549 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 610 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
611 {
612 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
613 }
614
615 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
550 { 616 {
551 if (!Enabled) 617 if (!Enabled)
552 return null; 618 return null;
@@ -584,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
584 bool append = (AttachmentPt & 0x80) != 0; 650 bool append = (AttachmentPt & 0x80) != 0;
585 AttachmentPt &= 0x7f; 651 AttachmentPt &= 0x7f;
586 652
587 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); 653 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
588 } 654 }
589 655
590 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 656 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -649,26 +715,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
649 if (changed && m_scene.AvatarFactory != null) 715 if (changed && m_scene.AvatarFactory != null)
650 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 716 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
651 717
718 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
719
652 sp.RemoveAttachment(so); 720 sp.RemoveAttachment(so);
653 so.FromItemID = UUID.Zero; 721 so.FromItemID = UUID.Zero;
654 722
723 so.AttachedAvatar = UUID.Zero;
724 so.ClearPartAttachmentData();
725
655 SceneObjectPart rootPart = so.RootPart; 726 SceneObjectPart rootPart = so.RootPart;
727
728 rootPart.SetParentLocalId(0);
656 so.AbsolutePosition = absolutePos; 729 so.AbsolutePosition = absolutePos;
657 if (absoluteRot != Quaternion.Identity) 730 if (absoluteRot != Quaternion.Identity)
658 { 731 {
659 so.UpdateGroupRotationR(absoluteRot); 732 so.UpdateGroupRotationR(absoluteRot);
660 } 733 }
661 so.AttachedAvatar = UUID.Zero; 734
662 rootPart.SetParentLocalId(0); 735 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
663 so.ClearPartAttachmentData(); 736
664 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); 737 // not physical, not temporary, phaton, not volume detector
738// so.UpdatePrimFlags(rootPart.LocalId,false,false,true,rootPart.VolumeDetectActive);
739
740 // restore full physical state instead
741 so.ApplyPhysics();
742
665 so.HasGroupChanged = true; 743 so.HasGroupChanged = true;
666 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
667 rootPart.Rezzed = DateTime.Now; 744 rootPart.Rezzed = DateTime.Now;
668 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
669 so.AttachToBackup(); 745 so.AttachToBackup();
670 m_scene.EventManager.TriggerParcelPrimCountTainted(); 746 m_scene.EventManager.TriggerParcelPrimCountTainted();
671 rootPart.ScheduleFullUpdate(); 747
672 rootPart.ClearUndoState(); 748 rootPart.ClearUndoState();
673 749
674 List<UUID> uuids = new List<UUID>(); 750 List<UUID> uuids = new List<UUID>();
@@ -678,6 +754,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
678 } 754 }
679 755
680 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 756 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
757
758 // Attach (NULL) stops scripts. We don't want that. Resume them.
759 so.ResumeScripts();
760 so.ScheduleGroupForTerseUpdate();
761 so.RootPart.ScheduleFullUpdate();
681 } 762 }
682 763
683 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 764 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
@@ -848,8 +929,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
848 929
849 so.AttachedAvatar = sp.UUID; 930 so.AttachedAvatar = sp.UUID;
850 931
851 if (so.RootPart.PhysActor != null) 932 foreach (SceneObjectPart part in so.Parts)
852 so.RootPart.RemoveFromPhysics(); 933 {
934// if (part.KeyframeMotion != null)
935// part.KeyframeMotion.Suspend();
936
937 if (part.PhysActor != null)
938 {
939 part.RemoveFromPhysics();
940 }
941 }
853 942
854 so.AbsolutePosition = attachOffset; 943 so.AbsolutePosition = attachOffset;
855 so.RootPart.AttachedPos = attachOffset; 944 so.RootPart.AttachedPos = attachOffset;
@@ -971,6 +1060,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
971 // Remove the object from the scene so no more updates 1060 // Remove the object from the scene so no more updates
972 // are sent. Doing this before the below changes will ensure 1061 // are sent. Doing this before the below changes will ensure
973 // updates can't cause "HUD artefacts" 1062 // updates can't cause "HUD artefacts"
1063
974 m_scene.DeleteSceneObject(so, false, false); 1064 m_scene.DeleteSceneObject(so, false, false);
975 1065
976 // Prepare sog for storage 1066 // Prepare sog for storage
@@ -992,7 +1082,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
992 } 1082 }
993 1083
994 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 1084 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
995 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) 1085 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
996 { 1086 {
997 if (m_invAccessModule == null) 1087 if (m_invAccessModule == null)
998 return null; 1088 return null;
@@ -1043,7 +1133,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1043 // This will throw if the attachment fails 1133 // This will throw if the attachment fails
1044 try 1134 try
1045 { 1135 {
1046 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); 1136 if (doc != null)
1137 {
1138 objatt.LoadScriptState(doc);
1139 objatt.ResetOwnerChangeFlag();
1140 }
1141
1142 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
1047 } 1143 }
1048 catch (Exception e) 1144 catch (Exception e)
1049 { 1145 {
@@ -1197,7 +1293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1197 AttachmentPt &= 0x7f; 1293 AttachmentPt &= 0x7f;
1198 1294
1199 // Calls attach with a Zero position 1295 // Calls attach with a Zero position
1200 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) 1296 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, true, append))
1201 { 1297 {
1202 if (DebugLevel > 0) 1298 if (DebugLevel > 0)
1203 m_log.Debug( 1299 m_log.Debug(
@@ -1205,7 +1301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1205 + ", AttachmentPoint: " + AttachmentPt); 1301 + ", AttachmentPoint: " + AttachmentPt);
1206 1302
1207 // Save avatar attachment information 1303 // Save avatar attachment information
1208 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1304 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
1209 } 1305 }
1210 } 1306 }
1211 catch (Exception e) 1307 catch (Exception e)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ac3add..34b38b9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
200 Assert.That(so.Backup, Is.True); 200 Assert.That(so.Backup, Is.True);
201 201
202 m_numberOfAttachEventsFired = 0; 202 m_numberOfAttachEventsFired = 0;
203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
204 204
205 // Check status on scene presence 205 // Check status on scene presence
206 Assert.That(sp.HasAttachments(), Is.True); 206 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));
@@ -670,7 +670,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
670 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 670 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
671 671
672 SceneObjectGroup rezzedSo 672 SceneObjectGroup rezzedSo
673 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 673 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
674 674
675 // Wait for chat to signal rezzed script has been started. 675 // Wait for chat to signal rezzed script has been started.
676 m_chatEvent.WaitOne(60000); 676 m_chatEvent.WaitOne(60000);
@@ -689,7 +689,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
690 690
691 // Re-rez the attachment to check script running state 691 // Re-rez the attachment to check script running state
692 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 692 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
693 693
694 // Wait for chat to signal rezzed script has been started. 694 // Wait for chat to signal rezzed script has been started.
695 m_chatEvent.WaitOne(60000); 695 m_chatEvent.WaitOne(60000);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index cfb082b..cdcd6b9 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -188,27 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
188 // Process the visual params, this may change height as well 188 // Process the visual params, this may change height as well
189 if (visualParams != null) 189 if (visualParams != null)
190 { 190 {
191 // string[] visualParamsStrings = new string[visualParams.Length];
192 // for (int i = 0; i < visualParams.Length; i++)
193 // visualParamsStrings[i] = visualParams[i].ToString();
194 // m_log.DebugFormat(
195 // "[AVFACTORY]: Setting visual params for {0} to {1}",
196 // client.Name, string.Join(", ", visualParamsStrings));
197/*
198 float oldHeight = sp.Appearance.AvatarHeight;
199 changed = sp.Appearance.SetVisualParams(visualParams);
200
201 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
202 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
203 */
204// float oldoff = sp.Appearance.AvatarFeetOffset;
205// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
206 changed = sp.Appearance.SetVisualParams(visualParams); 191 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);
211
212 } 192 }
213 193
214 // Process the baked texture array 194 // Process the baked texture array
@@ -222,9 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
222 202
223// WriteBakedTexturesReport(sp, m_log.DebugFormat); 203// WriteBakedTexturesReport(sp, m_log.DebugFormat);
224 204
225 // If bake textures are missing and this is not an NPC, request a rebake from client 205 UpdateBakedTextureCache(sp, cacheItems);
226 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
227 RequestRebake(sp, true);
228 206
229 // This appears to be set only in the final stage of the appearance 207 // This appears to be set only in the final stage of the appearance
230 // update transaction. In theory, we should be able to do an immediate 208 // update transaction. In theory, we should be able to do an immediate
@@ -251,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
251 private void SendAppearance(ScenePresence sp) 229 private void SendAppearance(ScenePresence sp)
252 { 230 {
253 // Send the appearance to everyone in the scene 231 // Send the appearance to everyone in the scene
254 sp.SendAppearanceToAllOtherClients(); 232 sp.SendAppearanceToAllOtherAgents();
255 233
256 // Send animations back to the avatar as well 234 // Send animations back to the avatar as well
257 sp.Animator.SendAnimPack(); 235 sp.Animator.SendAnimPack();
@@ -377,114 +355,322 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 } 355 }
378 } 356 }
379 357
380 public bool ValidateBakedTextureCache(IScenePresence sp) 358 // called on textures update
359 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
381 { 360 {
382 bool defonly = true; // are we only using default textures 361 // npcs dont have baked cache
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 362 if (((ScenePresence)sp).isNPC)
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 363 return true;
385 WearableCacheItem[] wearableCache = null; 364
386 365 // uploaded baked textures will be in assets local cache
387 // Cache wearable data for teleport. 366 IAssetService cache = m_scene.AssetService;
388 // Only makes sense if there's a bake module and a cache module 367 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
389 if (bakedModule != null && cache != null) 368
369 int validDirtyBakes = 0;
370 int hits = 0;
371
372 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
373 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
374
375 if (wearableCache == null)
376 {
377 wearableCache = WearableCacheItem.GetDefaultCacheItem();
378 }
379
380 List<UUID> missing = new List<UUID>();
381
382 // Process received baked textures
383 for (int i = 0; i < cacheItems.Length; i++)
390 { 384 {
391 try 385 int idx = (int)cacheItems[i].TextureIndex;
386 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
387
388 // No face
389 if (face == null)
392 { 390 {
393 wearableCache = bakedModule.Get(sp.UUID); 391 // for some reason viewer is cleaning this
392 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
393 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
394 wearableCache[idx].CacheId = UUID.Zero;
395 wearableCache[idx].TextureID = UUID.Zero;
396 wearableCache[idx].TextureAsset = null;
397 continue;
394 } 398 }
395 catch (Exception) 399 else
396 { 400 {
401 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
402 {
403 wearableCache[idx].CacheId = UUID.Zero;
404 wearableCache[idx].TextureID = UUID.Zero;
405 wearableCache[idx].TextureAsset = null;
406 continue;
407 }
397 408
398 } 409/*
399 if (wearableCache != null) 410 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
400 {
401 for (int i = 0; i < wearableCache.Length; i++)
402 { 411 {
403 cache.Cache(wearableCache[i].TextureAsset); 412 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
413 {
414 wearableCache[idx].CacheId = cacheItems[i].CacheId;
415 validDirtyBakes++;
416
417 //assuming this can only happen if asset is in cache
418 }
419 hits++;
420 continue;
421 }
422*/
423 wearableCache[idx].TextureAsset = null;
424 if (cache != null)
425 wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString());
426
427 if (wearableCache[idx].TextureAsset != null)
428 {
429 if ( wearableCache[idx].TextureID != face.TextureID ||
430 wearableCache[idx].CacheId != cacheItems[i].CacheId)
431 validDirtyBakes++;
432
433 wearableCache[idx].TextureID = face.TextureID;
434 wearableCache[idx].CacheId = cacheItems[i].CacheId;
435 hits++;
436 }
437 else
438 {
439 wearableCache[idx].CacheId = UUID.Zero;
440 wearableCache[idx].TextureID = UUID.Zero;
441 wearableCache[idx].TextureAsset = null;
442 missing.Add(face.TextureID);
443 continue;
404 } 444 }
405 } 445 }
406 } 446 }
407 /* 447
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 448 sp.Appearance.WearableCacheItems = wearableCache;
409 if (invService.GetRootFolder(userID) != null) 449
450 if (missing.Count > 0)
410 { 451 {
411 WearableCacheItem[] wearableCache = null; 452 foreach (UUID id in missing)
412 if (bakedModule != null) 453 sp.ControllingClient.SendRebakeAvatarTextures(id);
454 }
455
456 if (validDirtyBakes > 0 && hits == cacheItems.Length)
457 {
458 // if we got a full set of baked textures save all in BakedTextureModule
459 if (m_BakedTextureModule != null)
413 { 460 {
414 try 461 m_log.Debug("[UpdateBakedCache] uploading to bakedModule cache");
462
463 m_BakedTextureModule.Store(sp.UUID, wearableCache);
464 }
465 }
466
467
468 // debug
469 m_log.Debug("[UpdateBakedCache] cache hits: " + hits.ToString() + " changed entries: " + validDirtyBakes.ToString() + " rebakes " + missing.Count);
470/*
471 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
472 {
473 int j = AvatarAppearance.BAKE_INDICES[iter];
474 m_log.Debug("[UpdateBCache] {" + iter + "/" +
475 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
476 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
477 sp.Appearance.WearableCacheItems[j].TextureID);
478 }
479*/
480 return (hits == cacheItems.Length);
481 }
482
483 // called when we get a new root avatar
484 public bool ValidateBakedTextureCache(IScenePresence sp)
485 {
486 int hits = 0;
487
488 if (((ScenePresence)sp).isNPC)
489 return true;
490
491 lock (m_setAppearanceLock)
492 {
493 IAssetService cache = m_scene.AssetService;
494 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
495 WearableCacheItem[] bakedModuleCache = null;
496
497 if (cache == null)
498 return false;
499
500 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
501
502 // big debug
503 m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
504/*
505 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
506 {
507 int j = AvatarAppearance.BAKE_INDICES[iter];
508 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
509 if (wearableCache == null)
510 {
511 if (face != null)
512 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
513 else
514 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
515 }
516 else
517 {
518 if (face != null)
519 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
520 "}: cc-" +
521 wearableCache[j].CacheId + ", ct-" +
522 wearableCache[j].TextureID
523 );
524 else
525 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
526 "}: cc-" +
527 wearableCache[j].CacheId + ", ct-" +
528 wearableCache[j].TextureID
529 );
530 }
531 }
532*/
533 bool wearableCacheValid = false;
534 if (wearableCache == null)
535 {
536 wearableCache = WearableCacheItem.GetDefaultCacheItem();
537 }
538 else
539 {
540 // we may have received a full cache
541 // check same coerence and store
542 wearableCacheValid = true;
543 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
415 { 544 {
416 wearableCache = bakedModule.Get(userID); 545 int idx = AvatarAppearance.BAKE_INDICES[i];
417 appearance.WearableCacheItems = wearableCache; 546 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
418 appearance.WearableCacheItemsDirty = false; 547 if (face != null)
419 foreach (WearableCacheItem item in wearableCache)
420 { 548 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; 549 if (face.TextureID == wearableCache[idx].TextureID &&
550 face.TextureID != UUID.Zero)
551 {
552 if (wearableCache[idx].TextureAsset != null)
553 {
554 hits++;
555 wearableCache[idx].TextureAsset.Temporary = true;
556 wearableCache[idx].TextureAsset.Local = true;
557 cache.Store(wearableCache[idx].TextureAsset);
558 continue;
559 }
560 if (cache.GetCached((wearableCache[idx].TextureID).ToString()) != null)
561 {
562 hits++;
563 continue;
564 }
565 }
566 wearableCacheValid = false;
422 } 567 }
423 } 568 }
424 catch (Exception) 569
570 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
571 if (wearableCacheValid)
572 m_log.Debug("[ValidateBakedCache] have valid local cache");
573 }
574
575 bool checkExternal = false;
576
577 if (!wearableCacheValid)
578 {
579 // only use external bake module on login condition check
580// ScenePresence ssp = null;
581// if (sp is ScenePresence)
425 { 582 {
426 583// ssp = (ScenePresence)sp;
584// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
585// bakedModule != null;
586
587 // or do it anytime we dont have the cache
588 checkExternal = bakedModule != null;
427 } 589 }
428 } 590 }
429 */
430 591
431 // Process the texture entry 592 if (checkExternal)
432 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
433 {
434 int idx = AvatarAppearance.BAKE_INDICES[i];
435 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
436
437 // No face, so lets check our baked service cache, teleport or login.
438 if (face == null)
439 { 593 {
440 if (wearableCache != null) 594 hits = 0;
595 bool gotbacked = false;
596
597 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
598 try
599 {
600 bakedModuleCache = bakedModule.Get(sp.UUID);
601 }
602 catch (Exception e)
441 { 603 {
442 // If we find the an appearance item, set it as the textureentry and the face 604 m_log.ErrorFormat(e.ToString());
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 605 bakedModuleCache = null;
444 if (searchitem != null) 606 }
607
608 if (bakedModuleCache != null)
609 {
610 m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
611
612 for (int i = 0; i < bakedModuleCache.Length; i++)
445 { 613 {
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); 614 int j = (int)bakedModuleCache[i].TextureIndex;
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; 615
448 face = sp.Appearance.Texture.FaceTextures[idx]; 616 if (bakedModuleCache[i].TextureAsset != null)
617 {
618 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
619 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
620 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
621 bakedModuleCache[i].TextureAsset.Temporary = true;
622 bakedModuleCache[i].TextureAsset.Local = true;
623 cache.Store(bakedModuleCache[i].TextureAsset);
624 }
449 } 625 }
450 else 626 gotbacked = true;
627 }
628
629 if (gotbacked)
630 {
631 // force the ones we got
632 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
451 { 633 {
452 // if there is no texture entry and no baked cache, skip it 634 int idx = AvatarAppearance.BAKE_INDICES[i];
635 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
636
637 if (sp.Appearance.Texture.FaceTextures[idx] == null)
638 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint)idx);
639 sp.Appearance.Texture.FaceTextures[idx].TextureID = wearableCache[idx].TextureID;
640 face = sp.Appearance.Texture.FaceTextures[idx];
641
642 // this should be removed
643 if (face.TextureID != UUID.Zero && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
644 hits++;
453 continue; 645 continue;
454 } 646 }
455 } 647 }
456 else
457 {
458 //No texture entry face and no cache. Skip this face.
459 continue;
460 }
461 } 648 }
462
463// m_log.DebugFormat(
464// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
465// face.TextureID, idx, client.Name, client.AgentId);
466 649
467 // if the texture is one of the "defaults" then skip it 650 sp.Appearance.WearableCacheItems = wearableCache;
468 // this should probably be more intelligent (skirt texture doesnt matter
469 // if the avatar isnt wearing a skirt) but if any of the main baked
470 // textures is default then the rest should be as well
471 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
472 continue;
473
474 defonly = false; // found a non-default texture reference
475 651
476 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
477 return false;
478 } 652 }
479 653
480// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 654 // debug
481 655 m_log.DebugFormat("[ValidateBakedCache]: Completed texture check for {0} {1} with {2} hits", sp.Name, sp.UUID, hits);
482 // If we only found default textures, then the appearance is not cached 656/*
483 return (defonly ? false : true); 657 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
658 {
659 int j = AvatarAppearance.BAKE_INDICES[iter];
660 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
661 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
662 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
663 sp.Appearance.WearableCacheItems[j].TextureID);
664 }
665*/
666 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
484 } 667 }
485 668
486 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 669 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
487 { 670 {
671 if (((ScenePresence)sp).isNPC)
672 return 0;
673
488 int texturesRebaked = 0; 674 int texturesRebaked = 0;
489// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 675// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
490 676
@@ -497,14 +683,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
497 if (face == null) 683 if (face == null)
498 continue; 684 continue;
499 685
500// m_log.DebugFormat(
501// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
502// face.TextureID, idx, client.Name, client.AgentId);
503
504 // if the texture is one of the "defaults" then skip it
505 // this should probably be more intelligent (skirt texture doesnt matter
506 // if the avatar isnt wearing a skirt) but if any of the main baked
507 // textures is default then the rest should be as well
508 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) 686 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
509 continue; 687 continue;
510 688
@@ -675,7 +853,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
675 853
676 if (invService.GetRootFolder(userID) != null) 854 if (invService.GetRootFolder(userID) != null)
677 { 855 {
678 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 856 for (int i = 0; i < appearance.Wearables.Length; i++)
679 { 857 {
680 for (int j = 0; j < appearance.Wearables[i].Count; j++) 858 for (int j = 0; j < appearance.Wearables[i].Count; j++)
681 { 859 {
@@ -1080,8 +1258,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1080 1258
1081 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 1259 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
1082 { 1260 {
1083 if (wear.Type < AvatarWearable.MAX_WEARABLES) 1261 // If the wearable type is larger than the current array, expand it
1084 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); 1262 if (avatAppearance.Wearables.Length <= wear.Type)
1263 {
1264 int currentLength = avatAppearance.Wearables.Length;
1265 AvatarWearable[] wears = avatAppearance.Wearables;
1266 Array.Resize(ref wears, wear.Type + 1);
1267 for (int i = currentLength ; i <= wear.Type ; i++)
1268 wears[i] = new AvatarWearable();
1269 avatAppearance.Wearables = wears;
1270 }
1271 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero);
1085 } 1272 }
1086 1273
1087 avatAppearance.GetAssetsFrom(sp.Appearance); 1274 avatAppearance.GetAssetsFrom(sp.Appearance);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 9513408..dd93449 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
182 eyesFace.TextureID = eyesTextureId; 182 eyesFace.TextureID = eyesTextureId;
183 183
184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
185 afm.SaveBakedTextures(userId); 185 afm.SaveBakedTextures(userId);
186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
187 187
diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
index 414f06a..c0686d9 100644
--- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
@@ -101,8 +101,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
101 if (m_URL == String.Empty) 101 if (m_URL == String.Empty)
102 return null; 102 return null;
103 103
104 int size = 0;
105
106 using (RestClient rc = new RestClient(m_URL)) 104 using (RestClient rc = new RestClient(m_URL))
107 { 105 {
108 List<WearableCacheItem> ret = new List<WearableCacheItem>(); 106 List<WearableCacheItem> ret = new List<WearableCacheItem>();
@@ -113,35 +111,34 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
113 111
114 try 112 try
115 { 113 {
116 Stream s = rc.Request(m_Auth); 114 using(Stream s = rc.Request(m_Auth))
117
118 using (XmlTextReader sr = new XmlTextReader(s))
119 { 115 {
120 sr.ReadStartElement("BakedAppearance"); 116 using(XmlTextReader sr = new XmlTextReader(s))
121 while (sr.LocalName == "BakedTexture")
122 { 117 {
123 string sTextureIndex = sr.GetAttribute("TextureIndex"); 118 sr.ReadStartElement("BakedAppearance");
124 int lTextureIndex = Convert.ToInt32(sTextureIndex); 119 while(sr.LocalName == "BakedTexture")
125 string sCacheId = sr.GetAttribute("CacheId");
126 UUID lCacheId = UUID.Zero;
127 if (!(UUID.TryParse(sCacheId, out lCacheId)))
128 { 120 {
121 string sTextureIndex = sr.GetAttribute("TextureIndex");
122 int lTextureIndex = Convert.ToInt32(sTextureIndex);
123 string sCacheId = sr.GetAttribute("CacheId");
124 UUID lCacheId = UUID.Zero;
125 if(!(UUID.TryParse(sCacheId,out lCacheId)))
126 {
129 // ?? Nothing here 127 // ?? Nothing here
128 }
129
130 sr.ReadStartElement("BakedTexture");
131 if(sr.Name=="AssetBase")
132 {
133 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
134 ret.Add(new WearableCacheItem() { CacheId = lCacheId,TextureIndex = (uint)lTextureIndex,TextureAsset = a,TextureID = a.FullID });
135 sr.ReadEndElement();
136 }
130 } 137 }
131 138 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}",ret.Count,id);
132 ++size;
133
134 sr.ReadStartElement("BakedTexture");
135 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
136 ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
137
138 sr.ReadEndElement();
139 } 139 }
140 140 return ret.ToArray();
141 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
142 } 141 }
143
144 return ret.ToArray();
145 } 142 }
146 catch (XmlException) 143 catch (XmlException)
147 { 144 {
@@ -150,13 +147,22 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
150 } 147 }
151 } 148 }
152 149
150 public void Store(UUID agentId)
151 {
152 }
153
154 public void UpdateMeshAvatar(UUID agentId)
155 {
156 }
157
153 public void Store(UUID agentId, WearableCacheItem[] data) 158 public void Store(UUID agentId, WearableCacheItem[] data)
154 { 159 {
155 if (m_URL == String.Empty) 160 if (m_URL == String.Empty)
156 return; 161 return;
157 162
163 int numberWears = 0;
158 MemoryStream reqStream; 164 MemoryStream reqStream;
159 165
160 using (MemoryStream bakeStream = new MemoryStream()) 166 using (MemoryStream bakeStream = new MemoryStream())
161 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null)) 167 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null))
162 { 168 {
@@ -164,15 +170,16 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
164 170
165 for (int i = 0; i < data.Length; i++) 171 for (int i = 0; i < data.Length; i++)
166 { 172 {
167 if (data[i] != null) 173 if (data[i] != null && data[i].TextureAsset != null)
168 { 174 {
169 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); 175 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
170 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); 176 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
171 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); 177 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
172 if (data[i].TextureAsset != null) 178// if (data[i].TextureAsset != null)
173 m_serializer.Serialize(bakeWriter, data[i].TextureAsset); 179 m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
174 180
175 bakeWriter.WriteEndElement(); 181 bakeWriter.WriteEndElement();
182 numberWears++;
176 } 183 }
177 } 184 }
178 185
@@ -182,17 +189,18 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
182 reqStream = new MemoryStream(bakeStream.ToArray()); 189 reqStream = new MemoryStream(bakeStream.ToArray());
183 } 190 }
184 191
185 RestClient rc = new RestClient(m_URL);
186 rc.AddResourcePath("bakes");
187 rc.AddResourcePath(agentId.ToString());
188
189 rc.RequestMethod = "POST";
190
191 Util.FireAndForget( 192 Util.FireAndForget(
192 delegate 193 delegate
193 { 194 {
194 rc.Request(reqStream, m_Auth); 195 using(RestClient rc = new RestClient(m_URL))
195 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", data.Length, agentId); 196 {
197 rc.AddResourcePath("bakes");
198 rc.AddResourcePath(agentId.ToString());
199 rc.RequestMethod = "POST";
200
201 rc.Request(reqStream, m_Auth);
202 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId);
203 }
196 }, null, "XBakesModule.Store" 204 }, null, "XBakesModule.Store"
197 ); 205 );
198 } 206 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..d83713b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -51,7 +51,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
51 private int m_saydistance = 20; 51 private int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 private int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 private int m_whisperdistance = 10;
54 54 private List<Scene> m_scenes = new List<Scene>();
55 private List<string> FreezeCache = new List<string>();
56 private string m_adminPrefix = "";
55 internal object m_syncy = new object(); 57 internal object m_syncy = new object();
56 58
57 internal IConfig m_config; 59 internal IConfig m_config;
@@ -69,21 +71,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 71 m_enabled = false;
70 return; 72 return;
71 } 73 }
74
75 m_whisperdistance = m_config.GetInt("whisper_distance", m_whisperdistance);
76 m_saydistance = m_config.GetInt("say_distance", m_saydistance);
77 m_shoutdistance = m_config.GetInt("shout_distance", m_shoutdistance);
78 m_adminPrefix = m_config.GetString("admin_prefix", "");
72 } 79 }
73
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
77 } 80 }
78 81
79 public virtual void AddRegion(Scene scene) 82 public virtual void AddRegion(Scene scene)
80 { 83 {
81 if (!m_enabled) 84 if (!m_enabled) return;
82 return;
83 85
84 scene.EventManager.OnNewClient += OnNewClient; 86 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 87 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 88 if (!m_scenes.Contains(scene))
89 {
90 m_scenes.Add(scene);
91 scene.EventManager.OnNewClient += OnNewClient;
92 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
93 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
94 }
95 }
87 96
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 97 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 98 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,12 +112,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 112
104 public virtual void RemoveRegion(Scene scene) 113 public virtual void RemoveRegion(Scene scene)
105 { 114 {
106 if (!m_enabled) 115 if (!m_enabled) return;
107 return;
108 116
109 scene.EventManager.OnNewClient -= OnNewClient; 117 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 118 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 119 if (m_scenes.Contains(scene))
120 {
121 scene.EventManager.OnNewClient -= OnNewClient;
122 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
123 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
124 m_scenes.Remove(scene);
125 }
126 }
112 } 127 }
113 128
114 public virtual void Close() 129 public virtual void Close()
@@ -165,7 +180,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 180 return;
166 } 181 }
167 182
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 183 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
184 {
185 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
186 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
187 }
188 else
189 {
190 DeliverChatToAvatars(ChatSourceType.Agent, c);
191 }
169 } 192 }
170 193
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 194 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,33 +202,61 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 202 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 203 {
181 string fromName = c.From; 204 string fromName = c.From;
205 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 206 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 207 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 208 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 209 IScene scene = c.Scene;
210 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 211 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 212 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 213
214 bool checkParcelHide = false;
215 UUID sourceParcelID = UUID.Zero;
216 Vector3 hidePos = fromPos;
217
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 218 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 219
192 switch (sourceType) 220 switch (sourceType)
193 { 221 {
194 case ChatSourceType.Agent: 222 case ChatSourceType.Agent:
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 223 if (!(scene is Scene))
224 {
225 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
226 scene.RegionInfo.RegionName, c.Sender.AgentId);
227 return;
228 }
229 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
196 fromPos = avatar.AbsolutePosition; 230 fromPos = avatar.AbsolutePosition;
197 fromName = avatar.Name; 231 fromName = avatar.Name;
198 fromID = c.Sender.AgentId; 232 fromID = c.Sender.AgentId;
233 if (avatar.GodLevel >= 200)
234 { // let gods speak to outside or things may get confusing
235 fromNamePrefix = m_adminPrefix;
236 checkParcelHide = false;
237 }
238 else
239 {
240 checkParcelHide = true;
241 }
242 destination = UUID.Zero; // Avatars cant "SayTo"
199 ownerID = c.Sender.AgentId; 243 ownerID = c.Sender.AgentId;
200 244
245 hidePos = fromPos;
201 break; 246 break;
202 247
203 case ChatSourceType.Object: 248 case ChatSourceType.Object:
204 fromID = c.SenderUUID; 249 fromID = c.SenderUUID;
205 250
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 251 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
252 {
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 253 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
208 254 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
255 {
256 checkParcelHide = true;
257 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
258 }
259 }
209 break; 260 break;
210 } 261 }
211 262
@@ -214,38 +265,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 265 message = message.Substring(0, 1000);
215 266
216// m_log.DebugFormat( 267// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 268// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 269// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 270
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 271 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 272
222 if (targetID == UUID.Zero) 273 if (checkParcelHide)
274 {
275 checkParcelHide = false;
276 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
277 {
278 ILandObject srcland = (scene as Scene).LandChannel.GetLandObject(hidePos.X, hidePos.Y);
279 if (srcland != null && !srcland.LandData.SeeAVs)
280 {
281 sourceParcelID = srcland.LandData.GlobalID;
282 checkParcelHide = true;
283 }
284 }
285 }
286
287 foreach (Scene s in m_scenes)
223 { 288 {
224 // This should use ForEachClient, but clients don't have a position. 289 // This should use ForEachClient, but clients don't have a position.
225 // If camera is moved into client, then camera position can be used 290 // If camera is moved into client, then camera position can be used
226 scene.ForEachScenePresence( 291 // MT: No, it can't, as chat is heard from the avatar position, not
292 // the camera position.
293
294 s.ForEachScenePresence(
227 delegate(ScenePresence presence) 295 delegate(ScenePresence presence)
228 { 296 {
229 if (TrySendChatMessage( 297 if (destination != UUID.Zero && presence.UUID != destination)
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 298 return;
231 receiverIDs.Add(presence.UUID); 299 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
300 if (Presencecheck != null)
301 {
302 // This will pass all chat from objects. Not
303 // perfect, but it will do. For now. Better
304 // than the prior behavior of muting all
305 // objects on a parcel with access restrictions
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && presence.GodLevel < 200)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (destination != UUID.Zero)
314 {
315 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
316 receiverIDs.Add(presence.UUID);
317 }
318 else
319 {
320 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
321 receiverIDs.Add(presence.UUID);
322 }
323 }
324 }
232 } 325 }
233 ); 326 );
234 } 327 }
235 else 328
236 { 329 (scene as Scene).EventManager.TriggerOnChatToClients(
237 // This is a send to a specific client eg from llRegionSayTo
238 // no need to check distance etc, jand send is as say
239 ScenePresence presence = scene.GetScenePresence(targetID);
240 if (presence != null && !presence.IsChildAgent)
241 {
242 if (TrySendChatMessage(
243 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
244 receiverIDs.Add(presence.UUID);
245 }
246 }
247
248 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 330 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 331 }
251 332
@@ -287,28 +368,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
287 } 368 }
288 369
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 370 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 371 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292 372
293 ((Scene)c.Scene).ForEachRootClient( 373 if (c.Scene != null)
294 delegate(IClientAPI client) 374 {
295 { 375 ((Scene)c.Scene).ForEachRootClient
296 // don't forward SayOwner chat from objects to 376 (
297 // non-owner agents 377 delegate(IClientAPI client)
298 if ((c.Type == ChatTypeEnum.Owner) && 378 {
299 (null != c.SenderObject) && 379 // don't forward SayOwner chat from objects to
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 380 // non-owner agents
301 return; 381 if ((c.Type == ChatTypeEnum.Owner) &&
302 382 (null != c.SenderObject) &&
303 client.SendChatMessage( 383 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 384 return;
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 385
306 386 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
307 receiverIDs.Add(client.AgentId); 387 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
308 }); 388 receiverIDs.Add(client.AgentId);
309 389 }
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 390 );
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 391 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
392 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
393 }
312 } 394 }
313 395
314 /// <summary> 396 /// <summary>
@@ -360,6 +442,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
360 return true; 442 return true;
361 } 443 }
362 444
445 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
446 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
447 {
448 System.Threading.Timer Timer;
449 if (flags == 0)
450 {
451 FreezeCache.Add(target.ToString());
452 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
453 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
454 Timers.Add(target, Timer);
455 }
456 else
457 {
458 FreezeCache.Remove(target.ToString());
459 Timers.TryGetValue(target, out Timer);
460 Timers.Remove(target);
461 Timer.Dispose();
462 }
463 }
464
465 private void OnEndParcelFrozen(object avatar)
466 {
467 UUID target = (UUID)avatar;
468 FreezeCache.Remove(target.ToString());
469 System.Threading.Timer Timer;
470 Timers.TryGetValue(target, out Timer);
471 Timers.Remove(target);
472 Timer.Dispose();
473 }
363 #region SimulatorFeaturesRequest 474 #region SimulatorFeaturesRequest
364 475
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 476 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index fc23b72..4e1958a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -183,10 +183,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
183 try 183 try
184 { 184 {
185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
186
187 if (obj == null) 186 if (obj == null)
188 return; 187 return;
189
190 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0 188 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
191 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage) 189 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
192 { 190 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index a896897..56819fa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -203,8 +203,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
203 { 203 {
204 m_scene.ForEachRootClient(delegate(IClientAPI client) 204 m_scene.ForEachRootClient(delegate(IClientAPI client)
205 { 205 {
206 client.SendBlueBoxMessage(fromAvatarID, fromAvatarName, 206 client.SendAgentAlertMessage(
207 message); 207 message, false);
208 }); 208 });
209 } 209 }
210 210
@@ -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/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 08e7dd2..d6c4d5b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -262,6 +262,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
262 client.OnDenyFriendRequest += OnDenyFriendRequest; 262 client.OnDenyFriendRequest += OnDenyFriendRequest;
263 client.OnTerminateFriendship += RemoveFriendship; 263 client.OnTerminateFriendship += RemoveFriendship;
264 client.OnGrantUserRights += GrantRights; 264 client.OnGrantUserRights += GrantRights;
265 client.OnFindAgent += FindFriend;
265 266
266 // We need to cache information for child agents as well as root agents so that friend edit/move/delete 267 // We need to cache information for child agents as well as root agents so that friend edit/move/delete
267 // permissions will work across borders where both regions are on different simulators. 268 // permissions will work across borders where both regions are on different simulators.
@@ -726,6 +727,64 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
726 } 727 }
727 } 728 }
728 729
730 public void FindFriend(IClientAPI remoteClient,UUID HunterID ,UUID PreyID)
731 {
732 UUID requester = remoteClient.AgentId;
733 if(requester != HunterID) // only allow client agent to be the hunter (?)
734 return;
735
736 FriendInfo[] friends = GetFriendsFromCache(requester);
737 if (friends.Length == 0)
738 return;
739
740 FriendInfo friend = GetFriend(friends, PreyID);
741 if (friend == null)
742 return;
743
744 if((friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
745 return;
746
747 Scene hunterScene = (Scene)remoteClient.Scene;
748
749 if(hunterScene == null)
750 return;
751
752 // check local
753 ScenePresence sp;
754 double px;
755 double py;
756 if(hunterScene.TryGetScenePresence(PreyID, out sp))
757 {
758 if(sp == null)
759 return;
760 px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X;
761 py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y;
762
763 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
764 return;
765 }
766
767 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { PreyID.ToString() });
768
769 if (friendSessions == null || friendSessions.Length == 0)
770 return;
771
772 PresenceInfo friendSession = friendSessions[0];
773 if (friendSession == null)
774 return;
775
776 GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID);
777
778 if(region == null)
779 return;
780
781 // we don't have presence location so point to a standard region center for now
782 px = region.RegionLocX + 128.0;
783 py = region.RegionLocY + 128.0;
784
785 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
786 }
787
729 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) 788 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights)
730 { 789 {
731 UUID requester = remoteClient.AgentId; 790 UUID requester = remoteClient.AgentId;
@@ -745,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
745 804
746 if (friend != null) // Found it 805 if (friend != null) // Found it
747 { 806 {
748 // Store it on the DB 807 // Store it on service
749 if (!StoreRights(requester, friendID, rights)) 808 if (!StoreRights(requester, friendID, rights))
750 { 809 {
751 remoteClient.SendAlertMessage("Unable to grant rights."); 810 remoteClient.SendAlertMessage("Unable to grant rights.");
@@ -869,28 +928,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
869 return false; 928 return false;
870 } 929 }
871 930
872 public bool LocalGrantRights(UUID userID, UUID friendID, int userFlags, int rights) 931 public bool LocalGrantRights(UUID userID, UUID friendID, int oldRights, int newRights)
873 { 932 {
874 IClientAPI friendClient = LocateClientObject(friendID); 933 IClientAPI friendClient = LocateClientObject(friendID);
875 if (friendClient != null) 934 if (friendClient != null)
876 { 935 {
877 bool onlineBitChanged = ((rights ^ userFlags) & (int)FriendRights.CanSeeOnline) != 0; 936 int changedRights = newRights ^ oldRights;
937 bool onlineBitChanged = (changedRights & (int)FriendRights.CanSeeOnline) != 0;
878 if (onlineBitChanged) 938 if (onlineBitChanged)
879 { 939 {
880 if ((rights & (int)FriendRights.CanSeeOnline) == 1) 940 if ((newRights & (int)FriendRights.CanSeeOnline) == 1)
881 friendClient.SendAgentOnline(new UUID[] { userID }); 941 friendClient.SendAgentOnline(new UUID[] { userID });
882 else 942 else
883 friendClient.SendAgentOffline(new UUID[] { userID }); 943 friendClient.SendAgentOffline(new UUID[] { userID });
884 } 944 }
885 else 945
886 { 946 if(changedRights != 0)
887 bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; 947 friendClient.SendChangeUserRights(userID, friendID, newRights);
888 if (canEditObjectsChanged)
889 friendClient.SendChangeUserRights(userID, friendID, rights);
890 }
891 948
892 // Update local cache 949 // Update local cache
893 UpdateLocalCache(userID, friendID, rights); 950 UpdateLocalCache(userID, friendID, newRights);
894 951
895 return true; 952 return true;
896 } 953 }
@@ -946,8 +1003,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
946 lock (m_Friends) 1003 lock (m_Friends)
947 { 1004 {
948 FriendInfo[] friends = GetFriendsFromCache(friendID); 1005 FriendInfo[] friends = GetFriendsFromCache(friendID);
949 FriendInfo finfo = GetFriend(friends, userID); 1006 if(friends != EMPTY_FRIENDS)
950 finfo.TheirFlags = rights; 1007 {
1008 FriendInfo finfo = GetFriend(friends, userID);
1009 if(finfo!= null)
1010 finfo.TheirFlags = rights;
1011 }
951 } 1012 }
952 } 1013 }
953 1014
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 13512a2..c421740 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -211,7 +211,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
211 { 211 {
212 UUID fromID = UUID.Zero; 212 UUID fromID = UUID.Zero;
213 UUID toID = UUID.Zero; 213 UUID toID = UUID.Zero;
214 int rights = 0, userFlags = 0; 214 int oldRights = 0, newRights = 0;
215 215
216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) 216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
217 return FailureResult(); 217 return FailureResult();
@@ -222,13 +222,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
222 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 222 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
223 return FailureResult(); 223 return FailureResult();
224 224
225 if (!Int32.TryParse(request["UserFlags"].ToString(), out userFlags)) 225 if (!Int32.TryParse(request["UserFlags"].ToString(), out oldRights))
226 return FailureResult(); 226 return FailureResult();
227 227
228 if (!Int32.TryParse(request["Rights"].ToString(), out rights)) 228 if (!Int32.TryParse(request["Rights"].ToString(), out newRights))
229 return FailureResult(); 229 return FailureResult();
230 230
231 if (m_FriendsModule.LocalGrantRights(UUID.Zero, UUID.Zero, userFlags, rights)) 231 if (m_FriendsModule.LocalGrantRights(fromID, toID, oldRights, newRights))
232 return SuccessResult(); 232 return SuccessResult();
233 233
234 return FailureResult(); 234 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 3b6d970..adb838c 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/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 2462ff8..3c82fd9 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 {
@@ -181,7 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
181 SendGridInstantMessageViaXMLRPC(im, result); 188 SendGridInstantMessageViaXMLRPC(im, result);
182 } 189 }
183 190
184 public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result) 191 public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
185 { 192 {
186 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; 193 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
187 194
@@ -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,104 +445,192 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 445 return resp;
426 } 446 }
427 447
448
428 /// <summary> 449 /// <summary>
429 /// delegate for sending a grid instant message asynchronously 450 /// delegate for sending a grid instant message asynchronously
430 /// </summary> 451 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); 452 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
453
454 private class GIM {
455 public GridInstantMessage im;
456 public MessageResultNotification result;
457 };
458
459 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
460 private int numInstantMessageThreads = 0;
432 461
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 462 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
434 { 463 {
435 GridInstantMessageDelegate icon = 464 lock (pendingInstantMessages) {
436 (GridInstantMessageDelegate)iar.AsyncState; 465 if (numInstantMessageThreads >= 4) {
437 icon.EndInvoke(iar); 466 GIM gim = new GIM();
467 gim.im = im;
468 gim.result = result;
469 pendingInstantMessages.Enqueue(gim);
470 } else {
471 ++ numInstantMessageThreads;
472 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
473 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
474 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
475 }
476 }
438 } 477 }
439 478
440 479
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 480 private void GridInstantMessageCompleted(IAsyncResult iar)
442 { 481 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 482 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
444 483 d.EndInvoke(iar);
445 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
446 } 484 }
447 485
448 /// <summary> 486 /// <summary>
449 /// Internal SendGridInstantMessage over XMLRPC method. 487 /// Internal SendGridInstantMessage over XMLRPC method.
450 /// </summary> 488 /// </summary>
451 /// <remarks> 489
452 /// This is called from within a dedicated thread. 490 /// <param name="prevRegionHandle">
453 /// </remarks> 491 /// Pass in 0 the first time this method is called. It will be called recursively with the last
454 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) 492 /// regionhandle tried
493 /// </param>
494 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
455 { 495 {
496 GIM gim;
497 do {
498 try {
499 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
500 } catch (Exception e) {
501 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
502 }
503 lock (pendingInstantMessages) {
504 if (pendingInstantMessages.Count > 0) {
505 gim = pendingInstantMessages.Dequeue();
506 im = gim.im;
507 result = gim.result;
508 } else {
509 gim = null;
510 -- numInstantMessageThreads;
511 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
512 }
513 }
514 } while (gim != null);
515 }
516
517 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
518 {
519
456 UUID toAgentID = new UUID(im.toAgentID); 520 UUID toAgentID = new UUID(im.toAgentID);
521 PresenceInfo upd = null;
457 UUID regionID; 522 UUID regionID;
458 bool needToLookupAgent; 523 bool lookupAgent = false;
459 524
460 lock (m_UserRegionMap) 525 lock (m_UserRegionMap)
461 needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
462
463 while (true)
464 { 526 {
465 if (needToLookupAgent) 527 if (m_UserRegionMap.ContainsKey(toAgentID))
466 { 528 {
467 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); 529 upd = new PresenceInfo();
530 upd.RegionID = m_UserRegionMap[toAgentID];
468 531
469 UUID foundRegionID = UUID.Zero; 532 // We need to compare the current regionhandle with the previous region handle
470 533 // or the recursive loop will never end because it will never try to lookup the agent again
471 if (presences != null) 534 if (prevRegionID == upd.RegionID)
472 { 535 {
473 foreach (PresenceInfo p in presences) 536 lookupAgent = true;
474 {
475 if (p.RegionID != UUID.Zero)
476 {
477 foundRegionID = p.RegionID;
478 break;
479 }
480 }
481 } 537 }
482
483 // If not found or the found region is the same as the last lookup, then message is undeliverable
484 if (foundRegionID == UUID.Zero || foundRegionID == regionID)
485 break;
486 else
487 regionID = foundRegionID;
488 } 538 }
489 539 else
490 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
491 if (reginfo == null)
492 { 540 {
493 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); 541 lookupAgent = true;
494 break;
495 } 542 }
543 }
496 544
497 // Try to send the message to the agent via the retrieved region.
498 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
499 msgdata["region_handle"] = 0;
500 bool imresult = doIMSending(reginfo, msgdata);
501 545
502 // If the message delivery was successful, then cache the entry. 546 // Are we needing to look-up an agent?
503 if (imresult) 547 if (lookupAgent)
548 {
549 // Non-cached user agent lookup.
550 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
551 if (presences != null && presences.Length > 0)
504 { 552 {
505 lock (m_UserRegionMap) 553 foreach (PresenceInfo p in presences)
506 { 554 {
507 m_UserRegionMap[toAgentID] = regionID; 555 if (p.RegionID != UUID.Zero)
556 {
557 upd = p;
558 break;
559 }
508 } 560 }
509 result(true);
510 return;
511 } 561 }
512 562
513 // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried 563 if (upd != null)
514 // to use a locally cached region ID. All subsequent attempts need to lookup agent details from 564 {
515 // the presence service. 565 // check if we've tried this before..
516 needToLookupAgent = true; 566 // This is one way to end the recursive loop
567 //
568 if (upd.RegionID == prevRegionID)
569 {
570 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
571 HandleUndeliverableMessage(im, result);
572 return;
573 }
574 }
575 else
576 {
577 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
578 HandleUndeliverableMessage(im, result);
579 return;
580 }
517 } 581 }
518 582
519 // If we reached this point then the message was not deliverable. Remove the bad cache entry and 583 if (upd != null)
520 // signal the delivery failure. 584 {
521 lock (m_UserRegionMap) 585 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
522 m_UserRegionMap.Remove(toAgentID); 586 upd.RegionID);
587 if (reginfo != null)
588 {
589 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
590 // Not actually used anymore, left in for compatibility
591 // Remove at next interface change
592 //
593 msgdata["region_handle"] = 0;
594 bool imresult = doIMSending(reginfo, msgdata);
595 if (imresult)
596 {
597 // IM delivery successful, so store the Agent's location in our local cache.
598 lock (m_UserRegionMap)
599 {
600 if (m_UserRegionMap.ContainsKey(toAgentID))
601 {
602 m_UserRegionMap[toAgentID] = upd.RegionID;
603 }
604 else
605 {
606 m_UserRegionMap.Add(toAgentID, upd.RegionID);
607 }
608 }
609 result(true);
610 }
611 else
612 {
613 // try again, but lookup user this time.
614 // Warning, this must call the Async version
615 // of this method or we'll be making thousands of threads
616 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
617 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
523 618
524 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); 619 // This is recursive!!!!!
525 HandleUndeliverableMessage(im, result); 620 SendGridInstantMessageViaXMLRPCAsync(im, result,
621 upd.RegionID);
622 }
623 }
624 else
625 {
626 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
627 HandleUndeliverableMessage(im, result);
628 }
629 }
630 else
631 {
632 HandleUndeliverableMessage(im, result);
633 }
526 } 634 }
527 635
528 /// <summary> 636 /// <summary>
@@ -622,8 +730,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
622 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
623 gim["region_id"] = new UUID(msg.RegionID).ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
624 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;
625 return gim; 735 return gim;
626 } 736 }
627
628 } 737 }
629} 738}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 9cdb1c2..369d480 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -39,6 +39,13 @@ using OpenSim.Region.Framework.Scenes;
39 39
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 41{
42 public struct SendReply
43 {
44 public bool Success;
45 public string Message;
46 public int Disposition;
47 }
48
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")]
43 public class OfflineMessageModule : ISharedRegionModule 50 public class OfflineMessageModule : ISharedRegionModule
44 { 51 {
@@ -49,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
49 private string m_RestURL = String.Empty; 56 private string m_RestURL = String.Empty;
50 IMessageTransferModule m_TransferModule = null; 57 IMessageTransferModule m_TransferModule = null;
51 private bool m_ForwardOfflineGroupMessages = true; 58 private bool m_ForwardOfflineGroupMessages = true;
59 private Dictionary<IClientAPI, List<UUID>> m_repliesSent= new Dictionary<IClientAPI, List<UUID>>();
52 60
53 public void Initialise(IConfigSource config) 61 public void Initialise(IConfigSource config)
54 { 62 {
@@ -168,11 +176,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
168 private void OnNewClient(IClientAPI client) 176 private void OnNewClient(IClientAPI client)
169 { 177 {
170 client.OnRetrieveInstantMessages += RetrieveInstantMessages; 178 client.OnRetrieveInstantMessages += RetrieveInstantMessages;
179 client.OnLogout += OnClientLoggedOut;
180 }
181
182 public void OnClientLoggedOut(IClientAPI client)
183 {
184 m_repliesSent.Remove(client);
171 } 185 }
172 186
173 private void RetrieveInstantMessages(IClientAPI client) 187 private void RetrieveInstantMessages(IClientAPI client)
174 { 188 {
175 if (m_RestURL != "") 189 if (m_RestURL == String.Empty)
190 {
191 return;
192 }
193 else
176 { 194 {
177 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 195 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
178 196
@@ -180,28 +198,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
180 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 198 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
181 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 199 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
182 200
183 if (msglist == null) 201 if (msglist != null)
184 { 202 {
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); 203 foreach (GridInstantMessage im in msglist)
186 return;
187 }
188
189 foreach (GridInstantMessage im in msglist)
190 {
191 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
192 // send it directly or else the item will be given twice
193 client.SendInstantMessage(im);
194 else
195 { 204 {
196 // Send through scene event manager so all modules get a chance 205 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
197 // to look at this message before it gets delivered. 206 // send it directly or else the item will be given twice
198 // 207 client.SendInstantMessage(im);
199 // Needed for proper state management for stored group 208 else
200 // invitations 209 {
201 // 210 // Send through scene event manager so all modules get a chance
202 Scene s = FindScene(client.AgentId); 211 // to look at this message before it gets delivered.
203 if (s != null) 212 //
204 s.EventManager.TriggerIncomingInstantMessage(im); 213 // Needed for proper state management for stored group
214 // invitations
215 //
216
217 im.offline = 1;
218
219 Scene s = FindScene(client.AgentId);
220 if (s != null)
221 s.EventManager.TriggerIncomingInstantMessage(im);
222 }
205 } 223 }
206 } 224 }
207 } 225 }
@@ -213,7 +231,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
213 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 231 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
214 im.dialog != (byte)InstantMessageDialog.GroupNotice && 232 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
215 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 233 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
216 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 234 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
235 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
217 { 236 {
218 return; 237 return;
219 } 238 }
@@ -225,15 +244,60 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
225 return; 244 return;
226 } 245 }
227 246
247 Scene scene = FindScene(new UUID(im.fromAgentID));
248 if (scene == null)
249 scene = m_SceneList[0];
250
251// Avination new code
252// SendReply reply = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, SendReply>(
253// "POST", m_RestURL+"/SaveMessage/?scope=" +
254// scene.RegionInfo.ScopeID.ToString(), im);
255
256// current opensim and osgrid compatible
228 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 257 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
229 "POST", m_RestURL+"/SaveMessage/", im, 10000); 258 "POST", m_RestURL+"/SaveMessage/", im, 10000);
259// current opensim and osgrid compatible end
230 260
231 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 261 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
232 { 262 {
233 IClientAPI client = FindClient(new UUID(im.fromAgentID)); 263 IClientAPI client = FindClient(new UUID(im.fromAgentID));
234 if (client == null) 264 if (client == null)
235 return; 265 return;
266/* Avination new code
267 if (reply.Message == String.Empty)
268 reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved");
269
270 bool sendReply = true;
271
272 switch (reply.Disposition)
273 {
274 case 0: // Normal
275 break;
276 case 1: // Only once per user
277 if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID)))
278 {
279 sendReply = false;
280 }
281 else
282 {
283 if (!m_repliesSent.ContainsKey(client))
284 m_repliesSent[client] = new List<UUID>();
285 m_repliesSent[client].Add(new UUID(im.toAgentID));
286 }
287 break;
288 }
236 289
290 if (sendReply)
291 {
292 client.SendInstantMessage(new GridInstantMessage(
293 null, new UUID(im.toAgentID),
294 "System", new UUID(im.fromAgentID),
295 (byte)InstantMessageDialog.MessageFromAgent,
296 reply.Message,
297 false, new Vector3()));
298 }
299*/
300// current opensim and osgrid compatible
237 client.SendInstantMessage(new GridInstantMessage( 301 client.SendInstantMessage(new GridInstantMessage(
238 null, new UUID(im.toAgentID), 302 null, new UUID(im.toAgentID),
239 "System", new UUID(im.fromAgentID), 303 "System", new UUID(im.fromAgentID),
@@ -241,6 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
241 "User is not logged in. "+ 305 "User is not logged in. "+
242 (success ? "Message saved." : "Message not saved"), 306 (success ? "Message saved." : "Message not saved"),
243 false, new Vector3())); 307 false, new Vector3()));
308// current opensim and osgrid compatible end
244 } 309 }
245 } 310 }
246 } 311 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 8847414..8d11d20 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -565,6 +565,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
565 return null; 565 return null;
566 } 566 }
567 567
568 return account;
569 /*
568 try 570 try
569 { 571 {
570 string encpass = Util.Md5Hash(pass); 572 string encpass = Util.Md5Hash(pass);
@@ -585,6 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
585 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e); 587 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
586 return null; 588 return null;
587 } 589 }
590 */
588 } 591 }
589 592
590 /// <summary> 593 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bba48cc..085328c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -165,8 +165,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
165 if (im.binaryBucket.Length < 17) // Invalid 165 if (im.binaryBucket.Length < 17) // Invalid
166 return; 166 return;
167 167
168 UUID receipientID = new UUID(im.toAgentID); 168 UUID recipientID = new UUID(im.toAgentID);
169 ScenePresence user = scene.GetScenePresence(receipientID); 169 ScenePresence user = scene.GetScenePresence(recipientID);
170 UUID copyID; 170 UUID copyID;
171 171
172 // First byte is the asset type 172 // First byte is the asset type
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
181 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
182 182
183 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
184 = scene.GiveInventoryFolder(client, receipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(client, recipientID, client.AgentId, folderID, UUID.Zero);
185 185
186 if (folderCopy == null) 186 if (folderCopy == null)
187 { 187 {
@@ -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
@@ -453,18 +470,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
453 /// <param name="im"></param> 470 /// <param name="im"></param>
454 private void OnGridInstantMessage(GridInstantMessage im) 471 private void OnGridInstantMessage(GridInstantMessage im)
455 { 472 {
456 // Check if it's a type of message that we should handle
457 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
458 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
459 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
460 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
461 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
462 return;
463
464 m_log.DebugFormat(
465 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
466 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
467
468 // Check if this is ours to handle 473 // Check if this is ours to handle
469 // 474 //
470 Scene scene = FindClientScene(new UUID(im.toAgentID)); 475 Scene scene = FindClientScene(new UUID(im.toAgentID));
@@ -475,32 +480,100 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
475 // Find agent to deliver to 480 // Find agent to deliver to
476 // 481 //
477 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 482 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
483 if (user == null)
484 return;
478 485
479 if (user != null) 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)
480 { 490 {
481 user.ControllingClient.SendInstantMessage(im); 491 if (im.binaryBucket.Length < 17) // Invalid
492 return;
493
494 UUID recipientID = new UUID(im.toAgentID);
482 495
483 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 496 // First byte is the asset type
484 { 497 AssetType assetType = (AssetType)im.binaryBucket[0];
485 AssetType assetType = (AssetType)im.binaryBucket[0];
486 UUID inventoryID = new UUID(im.binaryBucket, 1);
487 498
488 IInventoryService invService = scene.InventoryService; 499 if (AssetType.Folder == assetType)
489 InventoryNodeBase node = null; 500 {
490 if (AssetType.Folder == assetType) 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);
514
515 InventoryItemBase given =
516 new InventoryItemBase(itemID, recipientID);
517 InventoryItemBase item =
518 scene.InventoryService.GetItem(given);
519
520 if (item != null)
491 { 521 {
492 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, new UUID(im.toAgentID)); 522 user.ControllingClient.SendBulkUpdateInventory(item);
493 node = invService.GetFolder(folder);
494 } 523 }
495 else 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);
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)
496 { 559 {
497 InventoryItemBase item = new InventoryItemBase(inventoryID, new UUID(im.toAgentID)); 560 user.ControllingClient.SendBulkUpdateInventory(item);
498 node = invService.GetItem(item);
499 } 561 }
500
501 if (node != null)
502 user.ControllingClient.SendBulkUpdateInventory(node);
503 } 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);
504 } 577 }
505 } 578 }
506 } 579 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 465ffbc..c517a30 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("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m = 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/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index c20369c..145f3db 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -873,6 +873,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
873 } 873 }
874 #endregion Notes 874 #endregion Notes
875 875
876
876 #region User Preferences 877 #region User Preferences
877 /// <summary> 878 /// <summary>
878 /// Updates the user preferences. 879 /// Updates the user preferences.
@@ -1402,5 +1403,182 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1402 return null; 1403 return null;
1403 } 1404 }
1404 #endregion Util 1405 #endregion Util
1406
1407 #region Web Util
1408 /// <summary>
1409 /// Sends json-rpc request with a serializable type.
1410 /// </summary>
1411 /// <returns>
1412 /// OSD Map.
1413 /// </returns>
1414 /// <param name='parameters'>
1415 /// Serializable type .
1416 /// </param>
1417 /// <param name='method'>
1418 /// Json-rpc method to call.
1419 /// </param>
1420 /// <param name='uri'>
1421 /// URI of json-rpc service.
1422 /// </param>
1423 /// <param name='jsonId'>
1424 /// Id for our call.
1425 /// </param>
1426 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1427 {
1428 if (jsonId == null)
1429 throw new ArgumentNullException ("jsonId");
1430 if (uri == null)
1431 throw new ArgumentNullException ("uri");
1432 if (method == null)
1433 throw new ArgumentNullException ("method");
1434 if (parameters == null)
1435 throw new ArgumentNullException ("parameters");
1436
1437 // Prep our payload
1438 OSDMap json = new OSDMap();
1439
1440 json.Add("jsonrpc", OSD.FromString("2.0"));
1441 json.Add("id", OSD.FromString(jsonId));
1442 json.Add("method", OSD.FromString(method));
1443
1444 json.Add("params", OSD.SerializeMembers(parameters));
1445
1446 string jsonRequestData = OSDParser.SerializeJsonString(json);
1447 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1448
1449 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1450
1451 webRequest.ContentType = "application/json-rpc";
1452 webRequest.Method = "POST";
1453
1454 Stream dataStream = webRequest.GetRequestStream();
1455 dataStream.Write(content, 0, content.Length);
1456 dataStream.Close();
1457
1458 WebResponse webResponse = null;
1459 try
1460 {
1461 webResponse = webRequest.GetResponse();
1462 }
1463 catch (WebException e)
1464 {
1465 Console.WriteLine("Web Error" + e.Message);
1466 Console.WriteLine ("Please check input");
1467 return false;
1468 }
1469
1470 OSDMap mret = new OSDMap();
1471
1472 using (Stream rstream = webResponse.GetResponseStream())
1473 {
1474 try
1475 {
1476 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1477 }
1478 catch (Exception e)
1479 {
1480 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1481 if (webResponse != null)
1482 webResponse.Close();
1483 return false;
1484 }
1485 }
1486
1487 if (webResponse != null)
1488 webResponse.Close();
1489
1490 if (mret.ContainsKey("error"))
1491 return false;
1492
1493 // get params...
1494 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1495 return true;
1496 }
1497
1498 /// <summary>
1499 /// Sends json-rpc request with OSD parameter.
1500 /// </summary>
1501 /// <returns>
1502 /// The rpc request.
1503 /// </returns>
1504 /// <param name='data'>
1505 /// data - incoming as parameters, outgong as result/error
1506 /// </param>
1507 /// <param name='method'>
1508 /// Json-rpc method to call.
1509 /// </param>
1510 /// <param name='uri'>
1511 /// URI of json-rpc service.
1512 /// </param>
1513 /// <param name='jsonId'>
1514 /// If set to <c>true</c> json identifier.
1515 /// </param>
1516 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1517 {
1518 OSDMap map = new OSDMap();
1519
1520 map["jsonrpc"] = "2.0";
1521 if(string.IsNullOrEmpty(jsonId))
1522 map["id"] = UUID.Random().ToString();
1523 else
1524 map["id"] = jsonId;
1525
1526 map["method"] = method;
1527 map["params"] = data;
1528
1529 string jsonRequestData = OSDParser.SerializeJsonString(map);
1530 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1531
1532 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1533 webRequest.ContentType = "application/json-rpc";
1534 webRequest.Method = "POST";
1535
1536 Stream dataStream = webRequest.GetRequestStream();
1537 dataStream.Write(content, 0, content.Length);
1538 dataStream.Close();
1539
1540 WebResponse webResponse = null;
1541 try
1542 {
1543 webResponse = webRequest.GetResponse();
1544 }
1545 catch (WebException e)
1546 {
1547 Console.WriteLine("Web Error" + e.Message);
1548 Console.WriteLine ("Please check input");
1549 return false;
1550 }
1551
1552 OSDMap response = new OSDMap();
1553
1554 using (Stream rstream = webResponse.GetResponseStream())
1555 {
1556 try
1557 {
1558 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1559 }
1560 catch (Exception e)
1561 {
1562 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1563 if (webResponse != null)
1564 webResponse.Close();
1565 return false;
1566 }
1567 }
1568
1569 if (webResponse != null)
1570 webResponse.Close();
1571
1572 if(response.ContainsKey("error"))
1573 {
1574 data = response["error"];
1575 return false;
1576 }
1577
1578 data = response;
1579
1580 return true;
1581 }
1582 #endregion Web Util
1405 } 1583 }
1406} 1584}
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 817ef85..44eee89 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,23 +118,46 @@ 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 ts = Util.EnvironmentTickCount();
124 return; 124/* this as no business here...
125 * must be done elsewhere ( and is )
126 int flags = m_scene.GetUserFlags(agentId);
127
128 m_log.ErrorFormat("[CreateCaps]: banCheck {0} ", Util.EnvironmentTickCountSubtract(ts));
125 129
130 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
131 return;
132*/
126 Caps caps; 133 Caps caps;
127 String capsObjectPath = GetCapsPath(agentId); 134 String capsObjectPath = GetCapsPath(agentId);
128 135
129 lock (m_capsObjects) 136 lock (m_capsObjects)
130 { 137 {
131 if (m_capsObjects.ContainsKey(agentId)) 138 if (m_capsObjects.ContainsKey(circuitCode))
132 { 139 {
133 Caps oldCaps = m_capsObjects[agentId]; 140 Caps oldCaps = m_capsObjects[circuitCode];
134 141
135 //m_log.WarnFormat( 142
136 // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ", 143 if (capsObjectPath == oldCaps.CapsObjectPath)
137 // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath); 144 {
145 m_log.WarnFormat(
146 "[CAPS]: Reusing caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ",
147 agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath);
148 return;
149 }
150 else
151 {
152 // not reusing add extra melanie cleanup
153 // Remove tge handlers. They may conflict with the
154 // new object created below
155 oldCaps.DeregisterHandlers();
156
157 // Better safe ... should not be needed but also
158 // no big deal
159 m_capsObjects.Remove(circuitCode);
160 }
138 } 161 }
139 162
140// m_log.DebugFormat( 163// m_log.DebugFormat(
@@ -145,13 +168,17 @@ namespace OpenSim.Region.CoreModules.Framework
145 (MainServer.Instance == null) ? 0: MainServer.Instance.Port, 168 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
146 capsObjectPath, agentId, m_scene.RegionInfo.RegionName); 169 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
147 170
148 m_capsObjects[agentId] = caps; 171 m_log.ErrorFormat("[CreateCaps]: new caps agent {0}, circuit {1}, path {2}, time {3} ",agentId,
149 } 172 circuitCode,caps.CapsObjectPath, Util.EnvironmentTickCountSubtract(ts));
150 173
174 m_capsObjects[circuitCode] = caps;
175 }
151 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 176 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
177// m_log.ErrorFormat("[CreateCaps]: end {0} ", Util.EnvironmentTickCountSubtract(ts));
178
152 } 179 }
153 180
154 public void RemoveCaps(UUID agentId) 181 public void RemoveCaps(UUID agentId, uint circuitCode)
155 { 182 {
156 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName); 183 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName);
157 lock (m_childrenSeeds) 184 lock (m_childrenSeeds)
@@ -164,14 +191,24 @@ namespace OpenSim.Region.CoreModules.Framework
164 191
165 lock (m_capsObjects) 192 lock (m_capsObjects)
166 { 193 {
167 if (m_capsObjects.ContainsKey(agentId)) 194 if (m_capsObjects.ContainsKey(circuitCode))
168 { 195 {
169 m_capsObjects[agentId].DeregisterHandlers(); 196 m_capsObjects[circuitCode].DeregisterHandlers();
170 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); 197 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]);
171 m_capsObjects.Remove(agentId); 198 m_capsObjects.Remove(circuitCode);
172 } 199 }
173 else 200 else
174 { 201 {
202 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
203 {
204 if (kvp.Value.AgentID == agentId)
205 {
206 kvp.Value.DeregisterHandlers();
207 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, kvp.Value);
208 m_capsObjects.Remove(kvp.Key);
209 return;
210 }
211 }
175 m_log.WarnFormat( 212 m_log.WarnFormat(
176 "[CAPS]: Received request to remove CAPS handler for root agent {0} in {1}, but no such CAPS handler found!", 213 "[CAPS]: Received request to remove CAPS handler for root agent {0} in {1}, but no such CAPS handler found!",
177 agentId, m_scene.RegionInfo.RegionName); 214 agentId, m_scene.RegionInfo.RegionName);
@@ -179,19 +216,30 @@ namespace OpenSim.Region.CoreModules.Framework
179 } 216 }
180 } 217 }
181 218
182 public Caps GetCapsForUser(UUID agentId) 219 public Caps GetCapsForUser(uint circuitCode)
183 { 220 {
184 lock (m_capsObjects) 221 lock (m_capsObjects)
185 { 222 {
186 if (m_capsObjects.ContainsKey(agentId)) 223 if (m_capsObjects.ContainsKey(circuitCode))
187 { 224 {
188 return m_capsObjects[agentId]; 225 return m_capsObjects[circuitCode];
189 } 226 }
190 } 227 }
191 228
192 return null; 229 return null;
193 } 230 }
194 231
232 public void ActivateCaps(uint circuitCode)
233 {
234 lock (m_capsObjects)
235 {
236 if (m_capsObjects.ContainsKey(circuitCode))
237 {
238 m_capsObjects[circuitCode].Activate();
239 }
240 }
241 }
242
195 public void SetAgentCapsSeeds(AgentCircuitData agent) 243 public void SetAgentCapsSeeds(AgentCircuitData agent)
196 { 244 {
197 lock (m_capsPaths) 245 lock (m_capsPaths)
@@ -289,9 +337,9 @@ namespace OpenSim.Region.CoreModules.Framework
289 337
290 lock (m_capsObjects) 338 lock (m_capsObjects)
291 { 339 {
292 foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) 340 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
293 { 341 {
294 capsReport.AppendFormat("** User {0}:\n", kvp.Key); 342 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
295 Caps caps = kvp.Value; 343 Caps caps = kvp.Value;
296 344
297 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 345 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
@@ -339,6 +387,7 @@ namespace OpenSim.Region.CoreModules.Framework
339 387
340 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName) 388 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName)
341 { 389 {
390 /*
342 sb.AppendFormat("Capability name {0}\n", capName); 391 sb.AppendFormat("Capability name {0}\n", capName);
343 392
344 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 393 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -384,10 +433,12 @@ namespace OpenSim.Region.CoreModules.Framework
384 } 433 }
385 434
386 sb.Append(cdt.ToString()); 435 sb.Append(cdt.ToString());
436 */
387 } 437 }
388 438
389 private void BuildSummaryStatsByCapReport(StringBuilder sb) 439 private void BuildSummaryStatsByCapReport(StringBuilder sb)
390 { 440 {
441 /*
391 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 442 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
392 cdt.AddColumn("Name", 34); 443 cdt.AddColumn("Name", 34);
393 cdt.AddColumn("Req Received", 12); 444 cdt.AddColumn("Req Received", 12);
@@ -444,10 +495,12 @@ namespace OpenSim.Region.CoreModules.Framework
444 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); 495 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
445 496
446 sb.Append(cdt.ToString()); 497 sb.Append(cdt.ToString());
498 */
447 } 499 }
448 500
449 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams) 501 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams)
450 { 502 {
503 /*
451 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) 504 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
452 return; 505 return;
453 506
@@ -478,10 +531,12 @@ namespace OpenSim.Region.CoreModules.Framework
478 } 531 }
479 532
480 MainConsole.Instance.Output(sb.ToString()); 533 MainConsole.Instance.Output(sb.ToString());
534 */
481 } 535 }
482 536
483 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp) 537 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp)
484 { 538 {
539 /*
485 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root"); 540 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root");
486 541
487 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 542 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -507,10 +562,12 @@ namespace OpenSim.Region.CoreModules.Framework
507 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled); 562 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
508 563
509 sb.Append(cdt.ToString()); 564 sb.Append(cdt.ToString());
565 */
510 } 566 }
511 567
512 private void BuildSummaryStatsByUserReport(StringBuilder sb) 568 private void BuildSummaryStatsByUserReport(StringBuilder sb)
513 { 569 {
570 /*
514 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 571 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
515 cdt.AddColumn("Name", 32); 572 cdt.AddColumn("Name", 32);
516 cdt.AddColumn("Type", 5); 573 cdt.AddColumn("Type", 5);
@@ -550,6 +607,7 @@ namespace OpenSim.Region.CoreModules.Framework
550 ); 607 );
551 608
552 sb.Append(cdt.ToString()); 609 sb.Append(cdt.ToString());
610 */
553 } 611 }
554 612
555 private class CapTableRow 613 private class CapTableRow
@@ -566,4 +624,4 @@ namespace OpenSim.Region.CoreModules.Framework
566 } 624 }
567 } 625 }
568 } 626 }
569} \ No newline at end of file 627}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index e4bc113..ed93f05 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -147,13 +147,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
147 // Add this agent in this region as a banned person 147 // Add this agent in this region as a banned person
148 public void Add(ulong pRegionHandle, UUID pAgentID) 148 public void Add(ulong pRegionHandle, UUID pAgentID)
149 { 149 {
150 this.Add(pRegionHandle, pAgentID, 45, 15);
151 }
152
153 public void Add(ulong pRegionHandle, UUID pAgentID, double newTime, double extendTime)
154 {
150 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache)) 155 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
151 { 156 {
152 m_idCache = new ExpiringCache<ulong, DateTime>(); 157 m_idCache = new ExpiringCache<ulong, DateTime>();
153 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45)); 158 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
154 } 159 }
155 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 160 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(extendTime), TimeSpan.FromSeconds(extendTime));
156 } 161 }
162
157 // Remove the agent from the region's banned list 163 // Remove the agent from the region's banned list
158 public void Remove(ulong pRegionHandle, UUID pAgentID) 164 public void Remove(ulong pRegionHandle, UUID pAgentID)
159 { 165 {
@@ -163,6 +169,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
163 } 169 }
164 } 170 }
165 } 171 }
172
166 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache(); 173 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
167 174
168 private IEventQueue m_eqModule; 175 private IEventQueue m_eqModule;
@@ -451,16 +458,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
451 } 458 }
452 459
453 // TODO: Get proper AVG Height 460 // TODO: Get proper AVG Height
454 float localAVHeight = 1.56f; 461 float localHalfAVHeight = 0.8f;
462 if (sp.Appearance != null)
463 localHalfAVHeight = sp.Appearance.AvatarHeight / 2;
464
455 float posZLimit = 22; 465 float posZLimit = 22;
456 466
457 // TODO: Check other Scene HeightField 467 // TODO: Check other Scene HeightField
458 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; 468 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
459 469
460 float newPosZ = posZLimit + localAVHeight; 470 posZLimit += localHalfAVHeight + 0.1f;
461 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 471
472 if ((position.Z < posZLimit) && !(Single.IsInfinity(posZLimit) || Single.IsNaN(posZLimit)))
462 { 473 {
463 position.Z = newPosZ; 474 position.Z = posZLimit;
464 } 475 }
465 476
466 if (sp.Flying) 477 if (sp.Flying)
@@ -559,9 +570,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
559 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY); 570 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
560 571
561 MapBlockData block = new MapBlockData(); 572 MapBlockData block = new MapBlockData();
562 block.X = (ushort)regX; 573 block.X = (ushort)(regX);
563 block.Y = (ushort)regY; 574 block.Y = (ushort)(regY);
564 block.Access = (byte)SimAccess.Down; 575 block.Access = (byte)SimAccess.Down; // == not there
565 576
566 List<MapBlockData> blocks = new List<MapBlockData>(); 577 List<MapBlockData> blocks = new List<MapBlockData>();
567 blocks.Add(block); 578 blocks.Add(block);
@@ -696,10 +707,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
696 return; 707 return;
697 } 708 }
698 709
699 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
700 Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
701 Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
702
703 ulong destinationHandle = finalDestination.RegionHandle; 710 ulong destinationHandle = finalDestination.RegionHandle;
704 711
705 // Let's do DNS resolution only once in this process, please! 712 // Let's do DNS resolution only once in this process, please!
@@ -768,7 +775,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
768 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); 775 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
769 agentCircuit.startpos = position; 776 agentCircuit.startpos = position;
770 agentCircuit.child = true; 777 agentCircuit.child = true;
771 agentCircuit.Appearance = sp.Appearance; 778
779// agentCircuit.Appearance = sp.Appearance;
780// agentCircuit.Appearance = new AvatarAppearance(sp.Appearance, true, false);
781 agentCircuit.Appearance = new AvatarAppearance();
782 agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
783
772 if (currentAgentCircuit != null) 784 if (currentAgentCircuit != null)
773 { 785 {
774 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; 786 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -779,24 +791,51 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
779 agentCircuit.Id0 = currentAgentCircuit.Id0; 791 agentCircuit.Id0 = currentAgentCircuit.Id0;
780 } 792 }
781 793
782 // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 794 IClientIPEndpoint ipepClient;
783 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance, 795
784 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY)); 796 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
785 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY)) 797 Util.RegionHandleToRegionLoc(destinationHandle, out newRegionX, out newRegionY);
798 Util.RegionHandleToRegionLoc(sourceRegion.RegionHandle, out oldRegionX, out oldRegionY);
799 int oldSizeX = (int)sourceRegion.RegionSizeX;
800 int oldSizeY = (int)sourceRegion.RegionSizeY;
801 int newSizeX = finalDestination.RegionSizeX;
802 int newSizeY = finalDestination.RegionSizeY;
803
804 bool OutSideViewRange = NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY,
805 oldSizeX, oldSizeY, newSizeX, newSizeY);
806
807 if (OutSideViewRange)
786 { 808 {
787 // brand new agent, let's create a new caps seed 809 m_log.DebugFormat(
810 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
811 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
812
813 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
814 #region IP Translation for NAT
815 // Uses ipepClient above
816 if (sp.ClientView.TryGet(out ipepClient))
817 {
818 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
819 }
820 #endregion
788 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 821 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
789 } 822 }
823 else
824 {
825 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
826 if (agentCircuit.CapsPath == null)
827 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
828 }
790 829
791 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 830 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2
792 if (ctx.OutboundVersion >= 0.2f) 831 if (ctx.OutboundVersion >= 0.2f)
793 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 832 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange , ctx, out reason);
794 else 833 else
795 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 834 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange, ctx, out reason);
796 } 835 }
797 836
798 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 837 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
799 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 838 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
800 { 839 {
801 ulong destinationHandle = finalDestination.RegionHandle; 840 ulong destinationHandle = finalDestination.RegionHandle;
802 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 841 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
@@ -805,10 +844,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
805 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}", 844 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
806 sp.Name, Scene.Name, finalDestination.RegionName); 845 sp.Name, Scene.Name, finalDestination.RegionName);
807 846
847 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
848
808 // Let's create an agent there if one doesn't exist yet. 849 // Let's create an agent there if one doesn't exist yet.
809 // NOTE: logout will always be false for a non-HG teleport. 850 // NOTE: logout will always be false for a non-HG teleport.
810 bool logout = false; 851 bool logout = false;
811 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 852 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
812 { 853 {
813 m_interRegionTeleportFailures.Value++; 854 m_interRegionTeleportFailures.Value++;
814 855
@@ -846,28 +887,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
846 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 887 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
847 888
848 // OK, it got this agent. Let's close some child agents 889 // OK, it got this agent. Let's close some child agents
849 sp.CloseChildAgents(newRegionX, newRegionY);
850 890
851 IClientIPEndpoint ipepClient; 891 if (OutSideViewRange)
852 string capsPath = String.Empty;
853 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
854 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
855 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
856 { 892 {
857 m_log.DebugFormat(
858 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
859 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
860
861 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
862 #region IP Translation for NAT
863 // Uses ipepClient above
864 if (sp.ClientView.TryGet(out ipepClient))
865 {
866 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
867 }
868 #endregion
869 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
870
871 if (m_eqModule != null) 893 if (m_eqModule != null)
872 { 894 {
873 // The EnableSimulator message makes the client establish a connection with the destination 895 // The EnableSimulator message makes the client establish a connection with the destination
@@ -897,15 +919,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
897 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); 919 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
898 } 920 }
899 } 921 }
900 else
901 {
902 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
903 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
904 }
905 922
906 // Let's send a full update of the agent. This is a synchronous call. 923 // Let's send a full update of the agent. This is a synchronous call.
907 AgentData agent = new AgentData(); 924 AgentData agent = new AgentData();
908 sp.CopyTo(agent); 925 sp.CopyTo(agent);
926
927 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
928 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
929
909 agent.Position = agentCircuit.startpos; 930 agent.Position = agentCircuit.startpos;
910 SetCallbackURL(agent, sp.Scene.RegionInfo); 931 SetCallbackURL(agent, sp.Scene.RegionInfo);
911 932
@@ -927,7 +948,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
927 // destination region but the viewer cannot establish the connection (e.g. due to network issues between 948 // destination region but the viewer cannot establish the connection (e.g. due to network issues between
928 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then 949 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
929 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). 950 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
930 if (!UpdateAgent(reg, finalDestination, agent, sp)) 951 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
931 { 952 {
932 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 953 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
933 { 954 {
@@ -1007,7 +1028,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1007 return; 1028 return;
1008 } 1029 }
1009 1030
1010 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1011 1031
1012/* 1032/*
1013 // TODO: This may be 0.6. Check if still needed 1033 // TODO: This may be 0.6. Check if still needed
@@ -1020,18 +1040,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1020 } 1040 }
1021*/ 1041*/
1022 1042
1023 // May need to logout or other cleanup 1043 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1024 AgentHasMovedAway(sp, logout);
1025 1044
1026 // Well, this is it. The agent is over there. 1045 sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1027 KillEntity(sp.Scene, sp.LocalId);
1028 1046
1029 // Now let's make it officially a child agent 1047 // call HG hook
1030 sp.MakeChildAgent(); 1048 AgentHasMovedAway(sp, logout);
1049
1050 sp.HasMovedAway(!(OutSideViewRange || logout));
1051
1052 // Now let's make it officially a child agent
1053 sp.MakeChildAgent(destinationHandle);
1031 1054
1032 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1055 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1033 1056
1034 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1057 if (NeedsClosing(reg, OutSideViewRange))
1035 { 1058 {
1036 if (!sp.Scene.IncomingPreCloseClient(sp)) 1059 if (!sp.Scene.IncomingPreCloseClient(sp))
1037 return; 1060 return;
@@ -1043,26 +1066,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1043 // This sleep can be increased if necessary. However, whilst it's active, 1066 // This sleep can be increased if necessary. However, whilst it's active,
1044 // an agent cannot teleport back to this region if it has teleported away. 1067 // an agent cannot teleport back to this region if it has teleported away.
1045 Thread.Sleep(2000); 1068 Thread.Sleep(2000);
1046 1069 if (m_eqModule != null && !sp.DoNotCloseAfterTeleport)
1070 m_eqModule.DisableSimulator(sp.RegionHandle,sp.UUID);
1071 Thread.Sleep(500);
1047 sp.Scene.CloseAgent(sp.UUID, false); 1072 sp.Scene.CloseAgent(sp.UUID, false);
1048 } 1073 }
1049 else
1050 {
1051 // now we have a child agent in this region.
1052 sp.Reset();
1053 }
1054 } 1074 }
1055 1075
1056 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 1076 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1057 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 1077 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
1058 { 1078 {
1059 ulong destinationHandle = finalDestination.RegionHandle; 1079 ulong destinationHandle = finalDestination.RegionHandle;
1060 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1080 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1061 1081
1082 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);;
1083
1062 // Let's create an agent there if one doesn't exist yet. 1084 // Let's create an agent there if one doesn't exist yet.
1063 // NOTE: logout will always be false for a non-HG teleport. 1085 // NOTE: logout will always be false for a non-HG teleport.
1064 bool logout = false; 1086 bool logout = false;
1065 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 1087 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
1066 { 1088 {
1067 m_interRegionTeleportFailures.Value++; 1089 m_interRegionTeleportFailures.Value++;
1068 1090
@@ -1099,32 +1121,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1099 // Past this point we have to attempt clean up if the teleport fails, so update transfer state. 1121 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1100 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 1122 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1101 1123
1102 IClientIPEndpoint ipepClient;
1103 string capsPath = String.Empty;
1104 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
1105 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
1106 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
1107 {
1108 m_log.DebugFormat(
1109 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1110 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1111
1112 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1113 #region IP Translation for NAT
1114 // Uses ipepClient above
1115 if (sp.ClientView.TryGet(out ipepClient))
1116 {
1117 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1118 }
1119 #endregion
1120 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1121 }
1122 else
1123 {
1124 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1125 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1126 }
1127
1128 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, 1124 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1129 // where that neighbour simulator could otherwise request a child agent create on the source which then 1125 // where that neighbour simulator could otherwise request a child agent create on the source which then
1130 // closes our existing agent which is still signalled as root. 1126 // closes our existing agent which is still signalled as root.
@@ -1146,6 +1142,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1146 AgentData agent = new AgentData(); 1142 AgentData agent = new AgentData();
1147 sp.CopyTo(agent); 1143 sp.CopyTo(agent);
1148 agent.Position = agentCircuit.startpos; 1144 agent.Position = agentCircuit.startpos;
1145
1146 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
1147 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1148
1149 agent.SenderWantsToWaitForRoot = true; 1149 agent.SenderWantsToWaitForRoot = true;
1150 //SetCallbackURL(agent, sp.Scene.RegionInfo); 1150 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1151 1151
@@ -1158,7 +1158,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1158 // Send the Update. If this returns true, we know the client has contacted the destination 1158 // Send the Update. If this returns true, we know the client has contacted the destination
1159 // via CompleteMovementIntoRegion, so we can let go. 1159 // via CompleteMovementIntoRegion, so we can let go.
1160 // If it returns false, something went wrong, and we need to abort. 1160 // If it returns false, something went wrong, and we need to abort.
1161 if (!UpdateAgent(reg, finalDestination, agent, sp)) 1161 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
1162 { 1162 {
1163 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 1163 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1164 { 1164 {
@@ -1187,19 +1187,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1187 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex 1187 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex
1188 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are 1188 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are
1189 // abandoned without proper close by viewer but then re-used by an incoming connection. 1189 // abandoned without proper close by viewer but then re-used by an incoming connection.
1190 sp.CloseChildAgents(newRegionX, newRegionY); 1190 sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1191 1191
1192 // May need to logout or other cleanup 1192 sp.HasMovedAway(!(OutSideViewRange || logout));
1193 AgentHasMovedAway(sp, logout);
1194 1193
1195 // Well, this is it. The agent is over there. 1194 //HG hook
1196 KillEntity(sp.Scene, sp.LocalId); 1195 AgentHasMovedAway(sp, logout);
1197 1196
1198 // Now let's make it officially a child agent 1197 // Now let's make it officially a child agent
1199 sp.MakeChildAgent(); 1198 sp.MakeChildAgent(destinationHandle);
1199
1200
1200 1201
1201 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1202 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1202 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1203 // go by HG hook
1204 if (NeedsClosing(reg, OutSideViewRange))
1203 { 1205 {
1204 if (!sp.Scene.IncomingPreCloseClient(sp)) 1206 if (!sp.Scene.IncomingPreCloseClient(sp))
1205 return; 1207 return;
@@ -1210,8 +1212,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1210 // BEFORE THEY SETTLE IN THE NEW REGION. 1212 // BEFORE THEY SETTLE IN THE NEW REGION.
1211 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR 1213 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1212 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS. 1214 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1213 Thread.Sleep(15000); 1215
1214 1216 Thread.Sleep(14000);
1217 if (m_eqModule != null && !sp.DoNotCloseAfterTeleport)
1218 m_eqModule.DisableSimulator(sp.RegionHandle,sp.UUID);
1219 Thread.Sleep(1000);
1220
1215 // OK, it got this agent. Let's close everything 1221 // OK, it got this agent. Let's close everything
1216 // If we shouldn't close the agent due to some other region renewing the connection 1222 // If we shouldn't close the agent due to some other region renewing the connection
1217 // then this will be handled in IncomingCloseAgent under lock conditions 1223 // then this will be handled in IncomingCloseAgent under lock conditions
@@ -1220,11 +1226,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1220 1226
1221 sp.Scene.CloseAgent(sp.UUID, false); 1227 sp.Scene.CloseAgent(sp.UUID, false);
1222 } 1228 }
1229/*
1223 else 1230 else
1224 { 1231 {
1225 // now we have a child agent in this region. 1232 // now we have a child agent in this region.
1226 sp.Reset(); 1233 sp.Reset();
1227 } 1234 }
1235 */
1228 } 1236 }
1229 1237
1230 /// <summary> 1238 /// <summary>
@@ -1272,13 +1280,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1272 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); 1280 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
1273 } 1281 }
1274 1282
1275 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 1283 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
1276 { 1284 {
1277 GridRegion source = new GridRegion(Scene.RegionInfo); 1285 GridRegion source = new GridRegion(Scene.RegionInfo);
1278 source.RawServerURI = m_GatekeeperURI; 1286 source.RawServerURI = m_GatekeeperURI;
1279 1287
1280 logout = false; 1288 logout = false;
1281 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, out reason); 1289 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, ctx, out reason);
1282 1290
1283 if (success) 1291 if (success)
1284 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); 1292 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
@@ -1286,9 +1294,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1286 return success; 1294 return success;
1287 } 1295 }
1288 1296
1289 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) 1297 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp, EntityTransferContext ctx)
1290 { 1298 {
1291 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 1299 return Scene.SimulationService.UpdateAgent(finalDestination, agent, ctx);
1292 } 1300 }
1293 1301
1294 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) 1302 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
@@ -1305,10 +1313,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1305 /// </summary> 1313 /// </summary>
1306 /// <param name='sp'></param> 1314 /// <param name='sp'></param>
1307 /// <param name='logout'></param> 1315 /// <param name='logout'></param>
1316 ///
1317 /// now just a HG hook
1308 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) 1318 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
1309 { 1319 {
1310 if (sp.Scene.AttachmentsModule != null) 1320// if (sp.Scene.AttachmentsModule != null)
1311 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true); 1321// sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, logout);
1312 } 1322 }
1313 1323
1314 protected void KillEntity(Scene scene, uint localID) 1324 protected void KillEntity(Scene scene, uint localID)
@@ -1316,6 +1326,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1316 scene.SendKillObject(new List<uint> { localID }); 1326 scene.SendKillObject(new List<uint> { localID });
1317 } 1327 }
1318 1328
1329 // HG hook
1319 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message) 1330 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message)
1320 { 1331 {
1321 message = null; 1332 message = null;
@@ -1325,7 +1336,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1325 // This returns 'true' if the new region already has a child agent for our 1336 // This returns 'true' if the new region already has a child agent for our
1326 // incoming agent. The implication is that, if 'false', we have to create the 1337 // incoming agent. The implication is that, if 'false', we have to create the
1327 // child and then teleport into the region. 1338 // child and then teleport into the region.
1328 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1339 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY,
1340 int oldsizeX, int oldsizeY, int newsizeX, int newsizeY)
1329 { 1341 {
1330 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 1342 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
1331 { 1343 {
@@ -1338,15 +1350,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1338 1350
1339 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y); 1351 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1340 } 1352 }
1341 else 1353
1342 { 1354 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY,
1343 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1355 oldsizeX, oldsizeY, newsizeX, newsizeY);
1344 }
1345 } 1356 }
1346 1357
1347 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 1358 // HG Hook
1359 protected virtual bool NeedsClosing(GridRegion reg, bool OutViewRange)
1360
1348 { 1361 {
1349 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1362 return OutViewRange;
1350 } 1363 }
1351 1364
1352 #endregion 1365 #endregion
@@ -1429,105 +1442,143 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1429 1442
1430 #region Agent Crossings 1443 #region Agent Crossings
1431 1444
1432 // Given a position relative to the current region (which has previously been tested to 1445 public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position,
1433 // see that it is actually outside the current region), find the new region that the 1446 EntityTransferContext ctx, out string reason)
1434 // point is actually in. 1447 {
1435 // Returns the coordinates and information of the new region or 'null' of it doesn't exist. 1448 reason = String.Empty;
1449
1450 UUID agentID = agent.UUID;
1451 ulong destinyHandle = destiny.RegionHandle;
1452
1453 if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
1454 {
1455 return false;
1456 }
1457
1458 Scene ascene = agent.Scene;
1459 string homeURI = ascene.GetAgentHomeURI(agentID);
1460
1461
1462 if (!ascene.SimulationService.QueryAccess(destiny, agentID, homeURI, false, position,
1463 agent.Scene.GetFormatsOffered(), ctx, out reason))
1464 {
1465 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1466 return false;
1467 }
1468 return true;
1469 }
1470
1471 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, out Vector3 newpos)
1472 {
1473 string r = String.Empty;
1474 return GetDestination(scene, agentID, pos, ctx, out newpos, out r);
1475 }
1476
1477 // Given a position relative to the current region and outside of it
1478 // find the new region that the point is actually in.
1479 // returns 'null' if new region not found or if information
1480 // and new position relative to it
1481 // now only works for crossings
1482
1436 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, 1483 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
1437 EntityTransferContext ctx, out Vector3 newpos, out string failureReason) 1484 EntityTransferContext ctx, out Vector3 newpos, out string failureReason)
1438 { 1485 {
1439 newpos = pos; 1486 newpos = pos;
1440 failureReason = string.Empty; 1487 failureReason = string.Empty;
1441 string homeURI = scene.GetAgentHomeURI(agentID);
1442 1488
1443// m_log.DebugFormat( 1489// m_log.DebugFormat(
1444// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1490// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1445 1491
1446 // Compute world location of the object's position 1492 // Compute world location of the agente position
1447 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X; 1493 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1448 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y; 1494 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1449 1495
1450 // Call the grid service to lookup the region containing the new position. 1496 // Call the grid service to lookup the region containing the new position.
1451 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, 1497 GridRegion neighbourRegion = GetRegionContainingWorldLocation(
1452 presenceWorldX, presenceWorldY, 1498 scene.GridService, scene.RegionInfo.ScopeID,
1453 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY)); 1499 presenceWorldX, presenceWorldY,
1500 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1454 1501
1455 if (neighbourRegion != null) 1502 if (neighbourRegion == null)
1456 { 1503 {
1457 // Compute the entity's position relative to the new region 1504 return null;
1458 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX), 1505 }
1506 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1507 {
1508 return null;
1509 }
1510
1511 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1512
1513 // Compute the entity's position relative to the new region
1514 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1459 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY), 1515 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1460 pos.Z); 1516 pos.Z);
1461 1517
1462 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID)) 1518 string homeURI = scene.GetAgentHomeURI(agentID);
1463 {
1464 failureReason = "Cannot region cross into banned parcel";
1465 neighbourRegion = null;
1466 }
1467 else
1468 {
1469 // If not banned, make sure this agent is not in the list.
1470 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1471 }
1472 1519
1473 // Check to see if we have access to the target region. 1520 if (!scene.SimulationService.QueryAccess(
1474 if (neighbourRegion != null 1521 neighbourRegion, agentID, homeURI, false, newpos,
1475 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, homeURI, false, newpos, scene.GetFormatsOffered(), ctx, out failureReason)) 1522 scene.GetFormatsOffered(), ctx, out failureReason))
1476 {
1477 // remember banned
1478 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1479 neighbourRegion = null;
1480 }
1481 }
1482 else
1483 { 1523 {
1484 // The destination region just doesn't exist 1524 // remember the fail
1485 failureReason = "Cannot cross into non-existent region"; 1525 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1526 return null;
1486 } 1527 }
1487 1528
1488 if (neighbourRegion == null)
1489 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1490 LogHeader, scene.RegionInfo.RegionName,
1491 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1492 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1493 pos);
1494 else
1495 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
1496 LogHeader, neighbourRegion.RegionName,
1497 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1498 newpos.X, newpos.Y);
1499
1500 return neighbourRegion; 1529 return neighbourRegion;
1501 } 1530 }
1502 1531
1503 public bool Cross(ScenePresence agent, bool isFlying) 1532 public bool Cross(ScenePresence agent, bool isFlying)
1504 { 1533 {
1534 agent.IsInTransit = true;
1535 CrossAsyncDelegate d = CrossAsync;
1536 d.BeginInvoke(agent, isFlying, CrossCompleted, d);
1537 return true;
1538 }
1539
1540 private void CrossCompleted(IAsyncResult iar)
1541 {
1542 CrossAsyncDelegate icon = (CrossAsyncDelegate)iar.AsyncState;
1543 ScenePresence agent = icon.EndInvoke(iar);
1544
1545 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1546
1547 if(!agent.IsChildAgent)
1548 {
1549 // crossing failed
1550 agent.CrossToNewRegionFail();
1551 }
1552 agent.IsInTransit = false;
1553 }
1554
1555 public ScenePresence CrossAsync(ScenePresence agent, bool isFlying)
1556 {
1557 uint x;
1558 uint y;
1505 Vector3 newpos; 1559 Vector3 newpos;
1506 EntityTransferContext ctx = new EntityTransferContext(); 1560 EntityTransferContext ctx = new EntityTransferContext();
1507 string failureReason; 1561 string failureReason;
1508 1562
1509 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, 1563 Vector3 pos = agent.AbsolutePosition + agent.Velocity;
1564
1565 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
1510 ctx, out newpos, out failureReason); 1566 ctx, out newpos, out failureReason);
1511 if (neighbourRegion == null) 1567 if (neighbourRegion == null)
1512 { 1568 {
1513 agent.ControllingClient.SendAlertMessage(failureReason); 1569 if (failureReason != String.Empty)
1514 return false; 1570 agent.ControllingClient.SendAlertMessage(failureReason);
1571 return agent;
1515 } 1572 }
1516 1573
1517 agent.IsInTransit = true; 1574// agent.IsInTransit = true;
1518 1575
1519 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; 1576 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
1520 d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, ctx, CrossAgentToNewRegionCompleted, d); 1577 agent.IsInTransit = false;
1521 1578 return agent;
1522 Scene.EventManager.TriggerCrossAgentToNewRegion(agent, isFlying, neighbourRegion);
1523
1524 return true;
1525 } 1579 }
1526 1580
1527 1581 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene);
1528 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
1529 Vector3 position,
1530 Scene initiatingScene);
1531 1582
1532 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) 1583 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
1533 { 1584 {
@@ -1628,7 +1679,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1628 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1679 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1629 } 1680 }
1630 1681
1631 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) 1682 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx))
1632 { 1683 {
1633 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); 1684 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1634 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1685 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
@@ -1644,14 +1695,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1644 return agent; 1695 return agent;
1645 } 1696 }
1646 1697
1647 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) 1698 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx)
1648 { 1699 {
1700 int ts = Util.EnvironmentTickCount();
1649 try 1701 try
1650 { 1702 {
1651 AgentData cAgent = new AgentData(); 1703 AgentData cAgent = new AgentData();
1652 agent.CopyTo(cAgent); 1704 agent.CopyTo(cAgent);
1705
1706// agent.Appearance.WearableCacheItems = null;
1707
1653 cAgent.Position = pos; 1708 cAgent.Position = pos;
1654 1709
1710 cAgent.ChildrenCapSeeds = agent.KnownRegions;
1711
1655 if (isFlying) 1712 if (isFlying)
1656 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; 1713 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1657 1714
@@ -1661,7 +1718,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1661 // Beyond this point, extra cleanup is needed beyond removing transit state 1718 // Beyond this point, extra cleanup is needed beyond removing transit state
1662 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); 1719 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
1663 1720
1664 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) 1721 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent, ctx))
1665 { 1722 {
1666 // region doesn't take it 1723 // region doesn't take it
1667 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1724 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
@@ -1671,11 +1728,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1671 neighbourRegion.RegionName, agent.Name); 1728 neighbourRegion.RegionName, agent.Name);
1672 1729
1673 ReInstantiateScripts(agent); 1730 ReInstantiateScripts(agent);
1674 agent.AddToPhysicalScene(isFlying); 1731 if(agent.ParentID == 0 && agent.ParentUUID == UUID.Zero)
1732 agent.AddToPhysicalScene(isFlying);
1675 1733
1676 return false; 1734 return false;
1677 } 1735 }
1678 1736
1737 m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts));
1738
1679 } 1739 }
1680 catch (Exception e) 1740 catch (Exception e)
1681 { 1741 {
@@ -1693,7 +1753,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1693 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, 1753 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1694 bool isFlying, EntityTransferContext ctx) 1754 bool isFlying, EntityTransferContext ctx)
1695 { 1755 {
1696 agent.ControllingClient.RequestClientInfo();
1697 1756
1698 string agentcaps; 1757 string agentcaps;
1699 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) 1758 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
@@ -1704,6 +1763,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1704 } 1763 }
1705 1764
1706 // No turning back 1765 // No turning back
1766
1707 agent.IsChildAgent = true; 1767 agent.IsChildAgent = true;
1708 1768
1709 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1769 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
@@ -1715,7 +1775,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1715 if (m_eqModule != null) 1775 if (m_eqModule != null)
1716 { 1776 {
1717 m_eqModule.CrossRegion( 1777 m_eqModule.CrossRegion(
1718 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, 1778 neighbourRegion.RegionHandle, pos, vel2 /* agent.Velocity */,
1719 neighbourRegion.ExternalEndPoint, 1779 neighbourRegion.ExternalEndPoint,
1720 capsPath, agent.UUID, agent.ControllingClient.SessionId, 1780 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1721 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); 1781 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
@@ -1723,25 +1783,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1723 else 1783 else
1724 { 1784 {
1725 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader); 1785 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1726 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1786 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
1727 capsPath); 1787 capsPath);
1728 } 1788 }
1729 1789
1790/*
1791 // Backwards compatibility. Best effort
1792 if (version == 0f)
1793 {
1794 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1795 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1796 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1797 }
1798*/
1730 // SUCCESS! 1799 // SUCCESS!
1731 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); 1800 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
1732 1801
1733 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. 1802 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1734 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1803 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1735 1804
1736 agent.MakeChildAgent(); 1805 // this may need the attachments
1806
1807 agent.HasMovedAway(true);
1808
1809 agent.MakeChildAgent(neighbourRegion.RegionHandle);
1737 1810
1738 // FIXME: Possibly this should occur lower down after other commands to close other agents, 1811 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1739 // but not sure yet what the side effects would be. 1812 // but not sure yet what the side effects would be.
1740 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1813 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1741 1814
1742 // now we have a child agent in this region. Request all interesting data about other (root) agents 1815 agent.CloseChildAgents(false, neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1743 agent.SendOtherAgentsAvatarDataToClient();
1744 agent.SendOtherAgentsAppearanceToClient();
1745 1816
1746 // TODO: Check since what version this wasn't needed anymore. May be as old as 0.6 1817 // TODO: Check since what version this wasn't needed anymore. May be as old as 0.6
1747/* 1818/*
@@ -1753,14 +1824,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1753 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); 1824 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1754 } 1825 }
1755*/ 1826*/
1756 // Next, let's close the child agent connections that are too far away.
1757 uint neighbourx;
1758 uint neighboury;
1759 Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1760
1761 agent.CloseChildAgents(neighbourx, neighboury);
1762
1763 AgentHasMovedAway(agent, false);
1764 1827
1765 // the user may change their profile information in other region, 1828 // the user may change their profile information in other region,
1766 // so the userinfo in UserProfileCache is not reliable any more, delete it 1829 // so the userinfo in UserProfileCache is not reliable any more, delete it
@@ -1800,7 +1863,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1800 #region Enable Child Agent 1863 #region Enable Child Agent
1801 1864
1802 /// <summary> 1865 /// <summary>
1803 /// This informs a single neighbouring region about agent "avatar". 1866 /// This informs a single neighbouring region about agent "avatar", and avatar about it
1804 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1867 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1805 /// </summary> 1868 /// </summary>
1806 /// <param name="sp"></param> 1869 /// <param name="sp"></param>
@@ -1809,41 +1872,47 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1809 { 1872 {
1810 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName); 1873 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName);
1811 1874
1875 ulong currentRegionHandler = sp.Scene.RegionInfo.RegionHandle;
1876 ulong regionhandler = region.RegionHandle;
1877
1878 Dictionary<ulong, string> seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1879
1880 if (seeds.ContainsKey(regionhandler))
1881 seeds.Remove(regionhandler);
1882/*
1883 List<ulong> oldregions = new List<ulong>(seeds.Keys);
1884
1885 if (oldregions.Contains(currentRegionHandler))
1886 oldregions.Remove(currentRegionHandler);
1887*/
1888 if (!seeds.ContainsKey(currentRegionHandler))
1889 seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath);
1890
1812 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1891 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1813 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 1892 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1814 agent.BaseFolder = UUID.Zero; 1893 agent.BaseFolder = UUID.Zero;
1815 agent.InventoryFolder = UUID.Zero; 1894 agent.InventoryFolder = UUID.Zero;
1816 agent.startpos = new Vector3(128, 128, 70); 1895 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region);
1817 agent.child = true; 1896 agent.child = true;
1818 agent.Appearance = sp.Appearance; 1897 agent.Appearance = new AvatarAppearance();
1898 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1899
1819 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 1900 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1820 1901
1821 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID)); 1902 seeds.Add(regionhandler, agent.CapsPath);
1822 //m_log.DebugFormat("[XXX] Seeds 1 {0}", agent.ChildrenCapSeeds.Count);
1823 1903
1824 if (!agent.ChildrenCapSeeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle))
1825 agent.ChildrenCapSeeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1826 //m_log.DebugFormat("[XXX] Seeds 2 {0}", agent.ChildrenCapSeeds.Count);
1827 1904
1828 sp.AddNeighbourRegion(region.RegionHandle, agent.CapsPath); 1905// agent.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1829 //foreach (ulong h in agent.ChildrenCapSeeds.Keys) 1906 agent.ChildrenCapSeeds = null;
1830 // m_log.DebugFormat("[XXX] --> {0}", h);
1831 //m_log.DebugFormat("[XXX] Adding {0}", region.RegionHandle);
1832 if (agent.ChildrenCapSeeds.ContainsKey(region.RegionHandle))
1833 {
1834 m_log.WarnFormat(
1835 "[ENTITY TRANSFER]: Overwriting caps seed {0} with {1} for region {2} (handle {3}) for {4} in {5}",
1836 agent.ChildrenCapSeeds[region.RegionHandle], agent.CapsPath,
1837 region.RegionName, region.RegionHandle, sp.Name, Scene.Name);
1838 }
1839
1840 agent.ChildrenCapSeeds[region.RegionHandle] = agent.CapsPath;
1841 1907
1842 if (sp.Scene.CapsModule != null) 1908 if (sp.Scene.CapsModule != null)
1843 { 1909 {
1844 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, agent.ChildrenCapSeeds); 1910 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1845 } 1911 }
1846 1912
1913 sp.KnownRegions = seeds;
1914 sp.AddNeighbourRegionSizeInfo(region);
1915
1847 if (currentAgentCircuit != null) 1916 if (currentAgentCircuit != null)
1848 { 1917 {
1849 agent.ServiceURLs = currentAgentCircuit.ServiceURLs; 1918 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -1853,7 +1922,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1853 agent.Mac = currentAgentCircuit.Mac; 1922 agent.Mac = currentAgentCircuit.Mac;
1854 agent.Id0 = currentAgentCircuit.Id0; 1923 agent.Id0 = currentAgentCircuit.Id0;
1855 } 1924 }
1856 1925/*
1926 AgentPosition agentpos = null;
1927
1928 if (oldregions.Count > 0)
1929 {
1930 agentpos = new AgentPosition();
1931 agentpos.AgentID = new UUID(sp.UUID.Guid);
1932 agentpos.SessionID = sp.ControllingClient.SessionId;
1933 agentpos.Size = sp.Appearance.AvatarSize;
1934 agentpos.Center = sp.CameraPosition;
1935 agentpos.Far = sp.DrawDistance;
1936 agentpos.Position = sp.AbsolutePosition;
1937 agentpos.Velocity = sp.Velocity;
1938 agentpos.RegionHandle = currentRegionHandler;
1939 agentpos.Throttles = sp.ControllingClient.GetThrottlesPacked(1);
1940 agentpos.ChildrenCapSeeds = seeds;
1941 }
1942*/
1857 IPEndPoint external = region.ExternalEndPoint; 1943 IPEndPoint external = region.ExternalEndPoint;
1858 if (external != null) 1944 if (external != null)
1859 { 1945 {
@@ -1862,7 +1948,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1862 InformClientOfNeighbourCompleted, 1948 InformClientOfNeighbourCompleted,
1863 d); 1949 d);
1864 } 1950 }
1951/*
1952 if(oldregions.Count >0)
1953 {
1954 uint neighbourx;
1955 uint neighboury;
1956 UUID scope = sp.Scene.RegionInfo.ScopeID;
1957 foreach (ulong handler in oldregions)
1958 {
1959 // crap code
1960 Utils.LongToUInts(handler, out neighbourx, out neighboury);
1961 GridRegion neighbour = sp.Scene.GridService.GetRegionByPosition(scope, (int)neighbourx, (int)neighboury);
1962 sp.Scene.SimulationService.UpdateAgent(neighbour, agentpos);
1963 }
1964 }
1965 */
1865 } 1966 }
1967
1866 #endregion 1968 #endregion
1867 1969
1868 #region Enable Child Agents 1970 #region Enable Child Agents
@@ -1872,146 +1974,153 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1872 1974
1873 /// <summary> 1975 /// <summary>
1874 /// This informs all neighbouring regions about agent "avatar". 1976 /// This informs all neighbouring regions about agent "avatar".
1977 /// and as important informs the avatar about then
1875 /// </summary> 1978 /// </summary>
1876 /// <param name="sp"></param> 1979 /// <param name="sp"></param>
1877 public void EnableChildAgents(ScenePresence sp) 1980 public void EnableChildAgents(ScenePresence sp)
1878 { 1981 {
1982 // assumes that out of view range regions are disconnected by the previus region
1983
1879 List<GridRegion> neighbours = new List<GridRegion>(); 1984 List<GridRegion> neighbours = new List<GridRegion>();
1880 RegionInfo m_regionInfo = sp.Scene.RegionInfo; 1985 Scene spScene = sp.Scene;
1986 RegionInfo m_regionInfo = spScene.RegionInfo;
1881 1987
1882 if (m_regionInfo != null) 1988 if (m_regionInfo != null)
1883 { 1989 {
1884 neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); 1990 neighbours = GetNeighbors(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
1885 } 1991 }
1886 else 1992 else
1887 { 1993 {
1888 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); 1994 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
1889 } 1995 }
1890 1996
1891 /// We need to find the difference between the new regions where there are no child agents 1997 ulong currentRegionHandler = m_regionInfo.RegionHandle;
1892 /// and the regions where there are already child agents. We only send notification to the former.
1893 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
1894 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
1895 List<ulong> previousRegionNeighbourHandles;
1896 1998
1897 if (sp.Scene.CapsModule != null) 1999 LinkedList<ulong> previousRegionNeighbourHandles;
2000 Dictionary<ulong, string> seeds;
2001 ICapabilitiesModule capsModule = spScene.CapsModule;
2002
2003 if (capsModule != null)
1898 { 2004 {
1899 previousRegionNeighbourHandles = 2005 seeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(sp.UUID));
1900 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys); 2006 previousRegionNeighbourHandles = new LinkedList<ulong>(seeds.Keys);
1901 } 2007 }
1902 else 2008 else
1903 { 2009 {
1904 previousRegionNeighbourHandles = new List<ulong>(); 2010 seeds = new Dictionary<ulong, string>();
2011 previousRegionNeighbourHandles = new LinkedList<ulong>();
1905 } 2012 }
1906 2013
1907 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 2014 IClientAPI spClient = sp.ControllingClient;
1908 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1909
1910// Dump("Current Neighbors", neighbourHandles);
1911// Dump("Previous Neighbours", previousRegionNeighbourHandles);
1912// Dump("New Neighbours", newRegions);
1913// Dump("Old Neighbours", oldRegions);
1914 2015
1915 /// Update the scene presence's known regions here on this region 2016 if (!seeds.ContainsKey(currentRegionHandler))
1916 sp.DropOldNeighbours(oldRegions); 2017 seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath);
1917
1918 /// Collect as many seeds as possible
1919 Dictionary<ulong, string> seeds;
1920 if (sp.Scene.CapsModule != null)
1921 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1922 else
1923 seeds = new Dictionary<ulong, string>();
1924 2018
1925 //m_log.Debug(" !!! No. of seeds: " + seeds.Count); 2019 AgentCircuitData currentAgentCircuit =
1926 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) 2020 spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1927 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1928 2021
1929 /// Create the necessary child agents
1930 List<AgentCircuitData> cagents = new List<AgentCircuitData>(); 2022 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
2023 List<ulong> newneighbours = new List<ulong>();
2024
1931 foreach (GridRegion neighbour in neighbours) 2025 foreach (GridRegion neighbour in neighbours)
1932 { 2026 {
1933 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2027 ulong handler = neighbour.RegionHandle;
2028
2029 if (previousRegionNeighbourHandles.Contains(handler))
1934 { 2030 {
1935 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 2031 // agent already knows this region
1936 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 2032 previousRegionNeighbourHandles.Remove(handler);
1937 agent.BaseFolder = UUID.Zero; 2033 continue;
1938 agent.InventoryFolder = UUID.Zero; 2034 }
1939 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1940 agent.child = true;
1941 agent.Appearance = sp.Appearance;
1942 if (currentAgentCircuit != null)
1943 {
1944 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1945 agent.IPAddress = currentAgentCircuit.IPAddress;
1946 agent.Viewer = currentAgentCircuit.Viewer;
1947 agent.Channel = currentAgentCircuit.Channel;
1948 agent.Mac = currentAgentCircuit.Mac;
1949 agent.Id0 = currentAgentCircuit.Id0;
1950 }
1951 2035
1952 if (newRegions.Contains(neighbour.RegionHandle)) 2036 if (handler == currentRegionHandler)
1953 { 2037 continue;
1954 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 2038
1955 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath); 2039 // a new region to add
1956 seeds.Add(neighbour.RegionHandle, agent.CapsPath); 2040 AgentCircuitData agent = spClient.RequestClientInfo();
1957 } 2041 agent.BaseFolder = UUID.Zero;
1958 else 2042 agent.InventoryFolder = UUID.Zero;
1959 { 2043 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1960 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle); 2044 agent.child = true;
1961 } 2045 agent.Appearance = new AvatarAppearance();
2046 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1962 2047
1963 cagents.Add(agent); 2048 if (currentAgentCircuit != null)
2049 {
2050 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
2051 agent.IPAddress = currentAgentCircuit.IPAddress;
2052 agent.Viewer = currentAgentCircuit.Viewer;
2053 agent.Channel = currentAgentCircuit.Channel;
2054 agent.Mac = currentAgentCircuit.Mac;
2055 agent.Id0 = currentAgentCircuit.Id0;
1964 } 2056 }
1965 }
1966 2057
1967 /// Update all child agent with everyone's seeds 2058 newneighbours.Add(handler);
1968 foreach (AgentCircuitData a in cagents) 2059 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1969 { 2060 seeds.Add(handler, agent.CapsPath);
1970 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1971 }
1972 2061
1973 if (sp.Scene.CapsModule != null) 2062 agent.ChildrenCapSeeds = null;
1974 { 2063 cagents.Add(agent);
1975 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1976 } 2064 }
1977 sp.KnownRegions = seeds;
1978 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
1979 //avatar.DumpKnownRegions();
1980 2065
1981 bool newAgent = false; 2066 if (previousRegionNeighbourHandles.Contains(currentRegionHandler))
1982 int count = 0; 2067 previousRegionNeighbourHandles.Remove(currentRegionHandler);
1983 foreach (GridRegion neighbour in neighbours) 2068
1984 { 2069 // previousRegionNeighbourHandles now contains regions to forget
1985 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName); 2070 foreach (ulong handler in previousRegionNeighbourHandles)
1986 // Don't do it if there's already an agent in that region 2071 seeds.Remove(handler);
1987 if (newRegions.Contains(neighbour.RegionHandle)) 2072
1988 newAgent = true; 2073 /// Update all child agent with everyone's seeds
1989 else 2074 // foreach (AgentCircuitData a in cagents)
1990 newAgent = false; 2075 // a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1991// continue; 2076
2077 if (capsModule != null)
2078 capsModule.SetChildrenSeed(sp.UUID, seeds);
1992 2079
1993 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2080 sp.KnownRegions = seeds;
2081 sp.SetNeighbourRegionSizeInfo(neighbours);
2082
2083 AgentPosition agentpos = new AgentPosition();
2084 agentpos.AgentID = new UUID(sp.UUID.Guid);
2085 agentpos.SessionID = spClient.SessionId;
2086 agentpos.Size = sp.Appearance.AvatarSize;
2087 agentpos.Center = sp.CameraPosition;
2088 agentpos.Far = sp.DrawDistance;
2089 agentpos.Position = sp.AbsolutePosition;
2090 agentpos.Velocity = sp.Velocity;
2091 agentpos.RegionHandle = currentRegionHandler;
2092 agentpos.Throttles = spClient.GetThrottlesPacked(1);
2093 // agentpos.ChildrenCapSeeds = seeds;
2094
2095 Util.FireAndForget(delegate
2096 {
2097 Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start
2098 int count = 0;
2099
2100 foreach (GridRegion neighbour in neighbours)
1994 { 2101 {
2102 ulong handler = neighbour.RegionHandle;
1995 try 2103 try
1996 { 2104 {
1997 // Let's put this back at sync, so that it doesn't clog 2105 if (newneighbours.Contains(handler))
1998 // the network, especially for regions in the same physical server. 2106 {
1999 // We're really not in a hurry here. 2107 InformClientOfNeighbourAsync(sp, cagents[count], neighbour,
2000 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent); 2108 neighbour.ExternalEndPoint, true);
2001 //InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 2109 count++;
2002 //d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent, 2110 }
2003 // InformClientOfNeighbourCompleted, 2111 else if (!previousRegionNeighbourHandles.Contains(handler))
2004 // d); 2112 {
2113 spScene.SimulationService.UpdateAgent(neighbour, agentpos);
2114 }
2005 } 2115 }
2006
2007 catch (ArgumentOutOfRangeException) 2116 catch (ArgumentOutOfRangeException)
2008 { 2117 {
2009 m_log.ErrorFormat( 2118 m_log.ErrorFormat(
2010 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", 2119 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).",
2011 neighbour.ExternalHostName, 2120 neighbour.ExternalHostName,
2012 neighbour.RegionHandle, 2121 neighbour.RegionHandle,
2013 neighbour.RegionLocX, 2122 neighbour.RegionLocX,
2014 neighbour.RegionLocY); 2123 neighbour.RegionLocY);
2015 } 2124 }
2016 catch (Exception e) 2125 catch (Exception e)
2017 { 2126 {
@@ -2028,11 +2137,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2028 2137
2029 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes. 2138 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
2030 // throw e; 2139 // throw e;
2031
2032 } 2140 }
2033 } 2141 }
2034 count++; 2142 });
2035 }
2036 } 2143 }
2037 2144
2038 // Computes the difference between two region bases. 2145 // Computes the difference between two region bases.
@@ -2040,26 +2147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2040 // The first region is the home region of the passed scene presence. 2147 // The first region is the home region of the passed scene presence.
2041 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2148 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2042 { 2149 {
2043 /* 2150 return new Vector3(sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2044 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2045 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2046 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2047 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2048 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2049 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2050 return new Vector3(shiftx, shifty, 0f);
2051 */
2052 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2053 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY, 2151 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2054 0f); 2152 0f);
2055 } 2153 }
2056 2154
2057 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2058 {
2059 // Since we don't know how big the regions could be, we have to search a very large area
2060 // to find possible regions.
2061 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2062 }
2063 2155
2064 #region NotFoundLocationCache class 2156 #region NotFoundLocationCache class
2065 // A collection of not found locations to make future lookups 'not found' lookups quick. 2157 // A collection of not found locations to make future lookups 'not found' lookups quick.
@@ -2144,7 +2236,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2144 #endregion // NotFoundLocationCache class 2236 #endregion // NotFoundLocationCache class
2145 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache(); 2237 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2146 2238
2147 // Given a world position (fractional meter coordinate), get the GridRegion info for 2239// needed for current OSG or old grid code
2240
2241 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2242 {
2243 // Since we don't know how big the regions could be, we have to search a very large area
2244 // to find possible regions.
2245 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2246 }
2247
2248 // Given a world position, get the GridRegion info for
2148 // the region containing that point. 2249 // the region containing that point.
2149 // Someday this should be a method on GridService. 2250 // Someday this should be a method on GridService.
2150 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere 2251 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
@@ -2153,7 +2254,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2153 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, 2254 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2154 double px, double py, uint pSizeHint) 2255 double px, double py, uint pSizeHint)
2155 { 2256 {
2156 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: query, loc=<{1},{2}>", LogHeader, px, py); 2257 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2157 GridRegion ret = null; 2258 GridRegion ret = null;
2158 const double fudge = 2.0; 2259 const double fudge = 2.0;
2159 2260
@@ -2164,7 +2265,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2164 // thus re-ask the GridService about the location. 2265 // thus re-ask the GridService about the location.
2165 if (m_notFoundLocationCache.Contains(px, py)) 2266 if (m_notFoundLocationCache.Contains(px, py))
2166 { 2267 {
2167 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py); 2268// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2168 return null; 2269 return null;
2169 } 2270 }
2170 2271
@@ -2246,55 +2347,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2246 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg, 2347 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg,
2247 IPEndPoint endPoint, bool newAgent) 2348 IPEndPoint endPoint, bool newAgent)
2248 { 2349 {
2249 // Let's wait just a little to give time to originating regions to catch up with closing child agents
2250 // after a cross here
2251 Thread.Sleep(500);
2252 2350
2253 Scene scene = sp.Scene; 2351 if (newAgent)
2254 2352 {
2255 m_log.DebugFormat( 2353 Scene scene = sp.Scene;
2256 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2257 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2258 2354
2259 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); 2355 m_log.DebugFormat(
2356 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2357 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2260 2358
2261 string reason = String.Empty; 2359 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath);
2262 2360
2263 bool regionAccepted = scene.SimulationService.CreateAgent(null, reg, a, (uint)TeleportFlags.Default, out reason); 2361 string reason = String.Empty;
2264 2362
2265 if (regionAccepted && newAgent) 2363 EntityTransferContext ctx = new EntityTransferContext();
2266 { 2364 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, a, (uint)TeleportFlags.Default, ctx, out reason);
2267 if (m_eqModule != null) 2365
2366 if (regionAccepted)
2268 { 2367 {
2269 #region IP Translation for NAT 2368 // give time for createAgent to finish, since it is async and does grid services access
2270 IClientIPEndpoint ipepClient; 2369 Thread.Sleep(500);
2271 if (sp.ClientView.TryGet(out ipepClient)) 2370
2371 if (m_eqModule != null)
2272 { 2372 {
2273 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); 2373 #region IP Translation for NAT
2274 } 2374 IClientIPEndpoint ipepClient;
2275 #endregion 2375 if (sp.ClientView.TryGet(out ipepClient))
2376 {
2377 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
2378 }
2379 #endregion
2276 2380
2277 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + 2381 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
2278 "and EstablishAgentCommunication with seed cap {8}", LogHeader, 2382 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
2279 scene.RegionInfo.RegionName, sp.Name, 2383 scene.RegionInfo.RegionName, sp.Name,
2280 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath); 2384 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY, capsPath);
2281 2385
2282 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY); 2386 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
2283 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY); 2387 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2284 } 2388 }
2285 else 2389 else
2286 { 2390 {
2287 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint); 2391 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
2288 // TODO: make Event Queue disablable! 2392 // TODO: make Event Queue disablable!
2393 }
2394
2395 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2289 } 2396 }
2290 2397
2291 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint); 2398 if (!regionAccepted)
2399 m_log.WarnFormat(
2400 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2401 reg.RegionName, sp.Name, sp.UUID, reason);
2292 } 2402 }
2293 2403
2294 if (!regionAccepted)
2295 m_log.WarnFormat(
2296 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2297 reg.RegionName, sp.Name, sp.UUID, reason);
2298 } 2404 }
2299 2405
2300 /// <summary> 2406 /// <summary>
@@ -2327,7 +2433,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2327 /// <param name="pRegionLocX"></param> 2433 /// <param name="pRegionLocX"></param>
2328 /// <param name="pRegionLocY"></param> 2434 /// <param name="pRegionLocY"></param>
2329 /// <returns></returns> 2435 /// <returns></returns>
2330 protected List<GridRegion> GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) 2436 protected List<GridRegion> GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
2331 { 2437 {
2332 Scene pScene = avatar.Scene; 2438 Scene pScene = avatar.Scene;
2333 RegionInfo m_regionInfo = pScene.RegionInfo; 2439 RegionInfo m_regionInfo = pScene.RegionInfo;
@@ -2338,18 +2444,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2338 // view to include everything in the megaregion 2444 // view to include everything in the megaregion
2339 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 2445 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2340 { 2446 {
2341 // The area to check is as big as the current region. 2447 uint dd = (uint)avatar.DrawDistance;
2342 // We presume all adjacent regions are the same size as this region.
2343 uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
2344 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2345 2448
2346 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2; 2449 // until avatar movement updates client connections, we need to seend at least this current region imediate Neighbors
2347 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2; 2450 uint ddX = Math.Max(dd, Constants.RegionSize);
2451 uint ddY = Math.Max(dd, Constants.RegionSize);
2348 2452
2349 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2; 2453 ddX--;
2350 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2; 2454 ddY--;
2351 2455
2352 neighbours 2456 // reference to region edges. Should be avatar position
2457 uint startX = Util.RegionToWorldLoc(pRegionLocX);
2458 uint endX = startX + m_regionInfo.RegionSizeX;
2459 uint startY = Util.RegionToWorldLoc(pRegionLocY);
2460 uint endY = startY + m_regionInfo.RegionSizeY;
2461
2462 startX -= ddX;
2463 startY -= ddY;
2464 endX += ddX;
2465 endY += ddY;
2466
2467 neighbours
2353 = avatar.Scene.GridService.GetRegionRange( 2468 = avatar.Scene.GridService.GetRegionRange(
2354 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); 2469 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2355 } 2470 }
@@ -2365,72 +2480,70 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2365 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y)); 2480 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
2366 } 2481 }
2367 2482
2368// neighbours.ForEach(
2369// n =>
2370// m_log.DebugFormat(
2371// "[ENTITY TRANSFER MODULE]: Region flags for {0} as seen by {1} are {2}",
2372// n.RegionName, Scene.Name, n.RegionFlags != null ? n.RegionFlags.ToString() : "not present"));
2373
2374 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). 2483 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
2375 neighbours.RemoveAll( 2484 neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
2376 r =>
2377 r.RegionID == m_regionInfo.RegionID
2378 || (r.RegionFlags != null && (r.RegionFlags & OpenSim.Framework.RegionFlags.RegionOnline) == 0));
2379 2485
2380 return neighbours; 2486 return neighbours;
2381 } 2487 }
2488 #endregion
2489
2490 #region Agent Arrived
2382 2491
2383 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2492 public void AgentArrivedAtDestination(UUID id)
2384 { 2493 {
2385 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); }); 2494 m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
2386 } 2495 }
2387 2496
2388 // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2497 #endregion
2389 // {
2390 // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
2391 // }
2392 2498
2393 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2499 #region Object Transfers
2394 {
2395 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
2396 }
2397 2500
2398 private List<ulong> NeighbourHandles(List<GridRegion> neighbours) 2501 public GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition,out Vector3 newpos)
2399 { 2502 {
2400 List<ulong> handles = new List<ulong>(); 2503 newpos = targetPosition;
2401 foreach (GridRegion reg in neighbours) 2504
2505 Scene scene = grp.Scene;
2506 if (scene == null)
2507 return null;
2508
2509 int x = (int)targetPosition.X + (int)scene.RegionInfo.WorldLocX;
2510 if (targetPosition.X >= 0)
2511 x++;
2512 else
2513 x--;
2514
2515 int y = (int)targetPosition.Y + (int)scene.RegionInfo.WorldLocY;
2516 if (targetPosition.Y >= 0)
2517 y++;
2518 else
2519 y--;
2520
2521 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID,x,y);
2522 if (neighbourRegion == null)
2402 { 2523 {
2403 handles.Add(reg.RegionHandle); 2524 return null;
2404 } 2525 }
2405 return handles;
2406 }
2407 2526
2408// private void Dump(string msg, List<ulong> handles) 2527 float newRegionSizeX = neighbourRegion.RegionSizeX;
2409// { 2528 float newRegionSizeY = neighbourRegion.RegionSizeY;
2410// m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg); 2529 if (newRegionSizeX == 0)
2411// foreach (ulong handle in handles) 2530 newRegionSizeX = Constants.RegionSize;
2412// { 2531 if (newRegionSizeY == 0)
2413// uint x, y; 2532 newRegionSizeY = Constants.RegionSize;
2414// Utils.LongToUInts(handle, out x, out y);
2415// x = x / Constants.RegionSize;
2416// y = y / Constants.RegionSize;
2417// m_log.InfoFormat("({0}, {1})", x, y);
2418// }
2419// }
2420 2533
2421 #endregion
2422 2534
2423 #region Agent Arrived 2535 newpos.X = targetPosition.X - (neighbourRegion.RegionLocX - (int)scene.RegionInfo.WorldLocX);
2536 newpos.Y = targetPosition.Y - (neighbourRegion.RegionLocY - (int)scene.RegionInfo.WorldLocY);
2424 2537
2425 public void AgentArrivedAtDestination(UUID id)
2426 {
2427 m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
2428 }
2429 2538
2430 #endregion 2539 const float enterDistance = 0.2f;
2540 newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
2541 newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
2431 2542
2432 #region Object Transfers 2543 return neighbourRegion;
2544 }
2433 2545
2546/* not in use. -> CrossPrimGroupIntoNewRegion
2434 /// <summary> 2547 /// <summary>
2435 /// Move the given scene object into a new region depending on which region its absolute position has moved 2548 /// Move the given scene object into a new region depending on which region its absolute position has moved
2436 /// into. 2549 /// into.
@@ -2453,20 +2566,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2453 if (scene == null) 2566 if (scene == null)
2454 return; 2567 return;
2455 2568
2456 if (grp.RootPart.DIE_AT_EDGE)
2457 {
2458 // We remove the object here
2459 try
2460 {
2461 scene.DeleteSceneObject(grp, false);
2462 }
2463 catch (Exception)
2464 {
2465 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
2466 }
2467 return;
2468 }
2469
2470 // Remember the old group position in case the region lookup fails so position can be restored. 2569 // Remember the old group position in case the region lookup fails so position can be restored.
2471 Vector3 oldGroupPosition = grp.RootPart.GroupPosition; 2570 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2472 2571
@@ -2509,7 +2608,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2509 grp.ScheduleGroupForFullUpdate(); 2608 grp.ScheduleGroupForFullUpdate();
2510 } 2609 }
2511 } 2610 }
2512 2611*/
2513 /// <summary> 2612 /// <summary>
2514 /// Move the given scene object into a new region 2613 /// Move the given scene object into a new region
2515 /// </summary> 2614 /// </summary>
@@ -2519,7 +2618,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2519 /// true if the crossing itself was successful, false on failure 2618 /// true if the crossing itself was successful, false on failure
2520 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region 2619 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
2521 /// </returns> 2620 /// </returns>
2522 protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) 2621 public bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts)
2523 { 2622 {
2524 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); 2623 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
2525 2624
@@ -2551,7 +2650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2551 // We remove the object here 2650 // We remove the object here
2552 try 2651 try
2553 { 2652 {
2554 grp.Scene.DeleteSceneObject(grp, silent); 2653 grp.Scene.DeleteSceneObject(grp, silent, removeScripts);
2555 } 2654 }
2556 catch (Exception e) 2655 catch (Exception e)
2557 { 2656 {
@@ -2560,30 +2659,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2560 grp, e); 2659 grp, e);
2561 } 2660 }
2562 } 2661 }
2563/*
2564 * done on caller ( not in attachments crossing for now)
2565 else
2566 {
2567
2568 if (!grp.IsDeleted)
2569 {
2570 PhysicsActor pa = grp.RootPart.PhysActor;
2571 if (pa != null)
2572 {
2573 pa.CrossingFailure();
2574 if (grp.RootPart.KeyframeMotion != null)
2575 {
2576 // moved to KeyframeMotion.CrossingFailure
2577// grp.RootPart.Velocity = Vector3.Zero;
2578 grp.RootPart.KeyframeMotion.CrossingFailure();
2579// grp.SendGroupRootTerseUpdate();
2580 }
2581 }
2582 }
2583
2584 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
2585 }
2586 */
2587 } 2662 }
2588 else 2663 else
2589 { 2664 {
@@ -2625,7 +2700,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2625 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", 2700 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
2626 clone.UUID, destination.RegionName); 2701 clone.UUID, destination.RegionName);
2627 2702
2628 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent); 2703 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent,true);
2629 } 2704 }
2630 } 2705 }
2631 2706
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index a3109e0..e3c6c0d 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -299,7 +299,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
299 id, m_mod.Scene.RegionInfo.RegionName, currentState)); 299 id, m_mod.Scene.RegionInfo.RegionName, currentState));
300 } 300 }
301 301
302 int count = 200; 302 int count = 400;
303 303
304 // There should be no race condition here since no other code should be removing the agent transfer or 304 // There should be no race condition here since no other code should be removing the agent transfer or
305 // changing the state to another other than Transferring => ReceivedAtDestination. 305 // changing the state to another other than Transferring => ReceivedAtDestination.
@@ -354,4 +354,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
354 } 354 }
355 } 355 }
356 } 356 }
357} \ No newline at end of file 357}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index fa23590..1783e0a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -239,13 +239,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
239 return region; 239 return region;
240 } 240 }
241 241
242 protected override bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 242 protected override bool NeedsClosing(GridRegion reg, bool OutViewRange)
243 { 243 {
244 if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 244 if (OutViewRange)
245 return true; 245 return true;
246 246
247 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 247 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
248 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 248 if (flags == -1 || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
249 return true; 249 return true;
250 250
251 return false; 251 return false;
@@ -263,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
263 } 263 }
264 } 264 }
265 265
266 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 266 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
267 { 267 {
268 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI); 268 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
269 reason = string.Empty; 269 reason = string.Empty;
@@ -308,7 +308,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
308 } 308 }
309 } 309 }
310 310
311 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout); 311 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout);
312 }
313
314 public void TriggerTeleportHome(UUID id, IClientAPI client)
315 {
316 TeleportHome(id, client);
312 } 317 }
313 318
314 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) 319 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
@@ -328,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
328 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); 333 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
329 334
330 // Check wearables 335 // Check wearables
331 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 336 for (int i = 0; i < sp.Appearance.Wearables.Length ; i++)
332 { 337 {
333 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) 338 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
334 { 339 {
@@ -337,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
337 342
338 bool found = false; 343 bool found = false;
339 foreach (AvatarAppearance a in ExportedAppearance) 344 foreach (AvatarAppearance a in ExportedAppearance)
340 if (a.Wearables[i] != null) 345 if (i < a.Wearables.Length && a.Wearables[i] != null)
341 { 346 {
342 found = true; 347 found = true;
343 break; 348 break;
@@ -351,7 +356,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
351 356
352 found = false; 357 found = false;
353 foreach (AvatarAppearance a in ExportedAppearance) 358 foreach (AvatarAppearance a in ExportedAppearance)
354 if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) 359 if (i < a.Wearables.Length && sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
355 { 360 {
356 found = true; 361 found = true;
357 break; 362 break;
@@ -429,10 +434,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
429 // return base.UpdateAgent(reg, finalDestination, agentData, sp); 434 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
430 //} 435 //}
431 436
432 public override void TriggerTeleportHome(UUID id, IClientAPI client)
433 {
434 TeleportHome(id, client);
435 }
436 437
437 public override bool TeleportHome(UUID id, IClientAPI client) 438 public override bool TeleportHome(UUID id, IClientAPI client)
438 { 439 {
@@ -491,9 +492,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
491 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}", 492 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}",
492 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName); 493 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName);
493 494
494 DoTeleport( 495 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
495 sp, homeGatekeeper, finalDestination,
496 position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
497 return true; 496 return true;
498 } 497 }
499 498
@@ -760,4 +759,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
760 return region; 759 return region;
761 } 760 }
762 } 761 }
763} \ No newline at end of file 762}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 5a9efb8..e5373c3 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -178,49 +178,55 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
178 sbyte assetType, 178 sbyte assetType,
179 byte wearableType, uint nextOwnerMask, int creationDate) 179 byte wearableType, uint nextOwnerMask, int creationDate)
180 { 180 {
181 m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}", name, folderID); 181 m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}, transactionID {2}", name,
182 folderID, transactionID);
182 183
183 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) 184 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
184 return; 185 return;
185 186
186 if (transactionID == UUID.Zero) 187 InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId);
188 InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f);
189
190 if (folder == null || folder.Owner != remoteClient.AgentId)
191 return;
192
193 if (transactionID != UUID.Zero)
187 { 194 {
188 ScenePresence presence; 195 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
189 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 196 if (agentTransactions != null)
190 { 197 {
191 byte[] data = null; 198 if (agentTransactions.HandleItemCreationFromTransaction(
199 remoteClient, transactionID, folderID, callbackID, description,
200 name, invType, assetType, wearableType, nextOwnerMask))
201 return;
202 }
203 }
192 204
193 if (invType == (sbyte)InventoryType.Landmark && presence != null) 205 ScenePresence presence;
194 { 206 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
195 string suffix = string.Empty, prefix = string.Empty; 207 {
196 string strdata = GenerateLandmark(presence, out prefix, out suffix); 208 byte[] data = null;
197 data = Encoding.ASCII.GetBytes(strdata);
198 name = prefix + name;
199 description += suffix;
200 }
201 209
202 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 210 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.FullID, asset.Type, invType, nextOwnerMask, creationDate);
207 }
208 else
209 { 211 {
210 m_log.ErrorFormat( 212 string suffix = string.Empty, prefix = string.Empty;
211 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", 213 string strdata = GenerateLandmark(presence, out prefix, out suffix);
212 remoteClient.AgentId); 214 data = Encoding.ASCII.GetBytes(strdata);
215 name = prefix + name;
216 description += suffix;
213 } 217 }
218
219 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
220 m_Scene.AssetService.Store(asset);
221 m_Scene.CreateNewInventoryItem(
222 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
223 name, description, 0, callbackID, asset.FullID, asset.Type, invType, nextOwnerMask, creationDate);
214 } 224 }
215 else 225 else
216 { 226 {
217 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; 227 m_log.ErrorFormat(
218 if (agentTransactions != null) 228 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
219 { 229 remoteClient.AgentId);
220 agentTransactions.HandleItemCreationFromTransaction(
221 remoteClient, transactionID, folderID, callbackID, description,
222 name, invType, assetType, wearableType, nextOwnerMask);
223 }
224 } 230 }
225 } 231 }
226 232
@@ -272,6 +278,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
272 278
273 remoteClient.SendAlertMessage("Script saved"); 279 remoteClient.SendAlertMessage("Script saved");
274 } 280 }
281 else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet)
282 {
283 AnimationSet animSet = new AnimationSet(data);
284 if (!animSet.Validate(x => {
285 int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x);
286 int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
287 if ((perms & required) != required)
288 return false;
289 return true;
290 }))
291 {
292 data = animSet.ToBytes();
293 }
294 }
275 295
276 AssetBase asset = 296 AssetBase asset =
277 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString()); 297 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString());
@@ -379,33 +399,48 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
379 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient, 399 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
380 bool asAttachment) 400 bool asAttachment)
381 { 401 {
382 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 402 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
383// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 403 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
384 404 Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>();
385 Dictionary<SceneObjectGroup, KeyframeMotion> group2Keyframe = new Dictionary<SceneObjectGroup, KeyframeMotion>(); 405 // this possible is not needed if keyframes are saved
386 406 Dictionary<UUID, KeyframeMotion> originalKeyframes = new Dictionary<UUID, KeyframeMotion>();
407
387 foreach (SceneObjectGroup objectGroup in objlist) 408 foreach (SceneObjectGroup objectGroup in objlist)
388 { 409 {
389 if (objectGroup.RootPart.KeyframeMotion != null) 410 if (objectGroup.RootPart.KeyframeMotion != null)
390 { 411 {
391 objectGroup.RootPart.KeyframeMotion.Pause(); 412 objectGroup.RootPart.KeyframeMotion.Suspend();
392 group2Keyframe.Add(objectGroup, objectGroup.RootPart.KeyframeMotion);
393 objectGroup.RootPart.KeyframeMotion = null;
394 } 413 }
414 objectGroup.RootPart.SetForce(Vector3.Zero);
415 objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
395 416
396// Vector3 inventoryStoredPosition = new Vector3 417 originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
397// (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 418 objectGroup.RootPart.KeyframeMotion = null;
398// ? 250 419
399// : objectGroup.AbsolutePosition.X) 420 Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition;
400// , 421 originalPositions[objectGroup.UUID] = inventoryStoredPosition;
401// (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) 422 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
402// ? 250 423 originalRotations[objectGroup.UUID] = inventoryStoredRotation;
403// : objectGroup.AbsolutePosition.Y, 424
404// objectGroup.AbsolutePosition.Z); 425 // Restore attachment data after trip through the sim
405// 426 if (objectGroup.RootPart.AttachPoint > 0)
406// originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 427 {
407// 428 inventoryStoredPosition = objectGroup.RootPart.AttachedPos;
408// objectGroup.AbsolutePosition = inventoryStoredPosition; 429 inventoryStoredRotation = objectGroup.RootPart.AttachRotation;
430 }
431
432 // Trees could be attached and it's been done, but it makes
433 // no sense. State must be preserved because it's the tree type
434 if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
435 objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
436 {
437 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
438 if (objectGroup.RootPart.AttachPoint > 0)
439 objectGroup.RootPart.Shape.LastAttachPoint = objectGroup.RootPart.AttachPoint;
440 }
441
442 objectGroup.AbsolutePosition = inventoryStoredPosition;
443 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
409 444
410 // Make sure all bits but the ones we want are clear 445 // Make sure all bits but the ones we want are clear
411 // on take. 446 // on take.
@@ -433,9 +468,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
433 else 468 else
434 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); 469 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
435 470
436// // Restore the position of each group now that it has been stored to inventory. 471 // Restore the position of each group now that it has been stored to inventory.
437// foreach (SceneObjectGroup objectGroup in objlist) 472 foreach (SceneObjectGroup objectGroup in objlist)
438// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 473 {
474 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
475 objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID];
476 objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID];
477 if (objectGroup.RootPart.KeyframeMotion != null)
478 objectGroup.RootPart.KeyframeMotion.Resume();
479 }
439 480
440 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 481 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
441 482
@@ -492,7 +533,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
492 item.Name = asset.Name; 533 item.Name = asset.Name;
493 item.AssetType = asset.Type; 534 item.AssetType = asset.Type;
494 535
495 AddPermissions(item, objlist[0], objlist, remoteClient); 536 //preserve perms on return
537 if(DeRezAction.Return == action)
538 AddPermissions(item, objlist[0], objlist, null);
539 else
540 AddPermissions(item, objlist[0], objlist, remoteClient);
496 541
497 m_Scene.AddInventoryItem(item); 542 m_Scene.AddInventoryItem(item);
498 543
@@ -510,13 +555,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
510 } 555 }
511 } 556 }
512 557
513 // Restore KeyframeMotion
514 foreach (SceneObjectGroup objectGroup in group2Keyframe.Keys)
515 {
516 objectGroup.RootPart.KeyframeMotion = group2Keyframe[objectGroup];
517 objectGroup.RootPart.KeyframeMotion.Start();
518 }
519
520 // This is a hook to do some per-asset post-processing for subclasses that need that 558 // This is a hook to do some per-asset post-processing for subclasses that need that
521 if (remoteClient != null) 559 if (remoteClient != null)
522 ExportAsset(remoteClient.AgentId, asset.FullID); 560 ExportAsset(remoteClient.AgentId, asset.FullID);
@@ -543,15 +581,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
543 { 581 {
544 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; 582 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7;
545 uint allObjectsNextOwnerPerms = 0x7fffffff; 583 uint allObjectsNextOwnerPerms = 0x7fffffff;
546 uint allObjectsEveryOnePerms = 0x7fffffff;
547 uint allObjectsGroupPerms = 0x7fffffff;
548 584
585 // For the porposes of inventory, an object is modify if the prims
586 // are modify. This allows renaming an object that contains no
587 // mod items.
549 foreach (SceneObjectGroup grp in objsForEffectivePermissions) 588 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
550 { 589 {
551 effectivePerms &= grp.GetEffectivePermissions(); 590 uint groupPerms = grp.GetEffectivePermissions(true);
552 allObjectsNextOwnerPerms &= grp.RootPart.NextOwnerMask; 591 if ((grp.RootPart.BaseMask & (uint)PermissionMask.Modify) != 0)
553 allObjectsEveryOnePerms &= grp.RootPart.EveryoneMask; 592 groupPerms |= (uint)PermissionMask.Modify;
554 allObjectsGroupPerms &= grp.RootPart.GroupMask; 593
594 effectivePerms &= groupPerms;
555 } 595 }
556 effectivePerms |= (uint)PermissionMask.Move; 596 effectivePerms |= (uint)PermissionMask.Move;
557 597
@@ -565,11 +605,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
565 uint perms = effectivePerms; 605 uint perms = effectivePerms;
566 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms); 606 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms);
567 607
568 item.BasePermissions = perms & allObjectsNextOwnerPerms; 608 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
569 item.CurrentPermissions = item.BasePermissions; 609 item.CurrentPermissions = item.BasePermissions;
570 item.NextPermissions = perms & allObjectsNextOwnerPerms; 610 item.NextPermissions = perms & so.RootPart.NextOwnerMask;
571 item.EveryOnePermissions = allObjectsEveryOnePerms & allObjectsNextOwnerPerms; 611 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
572 item.GroupPermissions = allObjectsGroupPerms & allObjectsNextOwnerPerms; 612 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
573 613
574 // apply next owner perms on rez 614 // apply next owner perms on rez
575 item.CurrentPermissions |= SceneObjectGroup.SLAM; 615 item.CurrentPermissions |= SceneObjectGroup.SLAM;
@@ -585,9 +625,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
585 625
586 item.BasePermissions = effectivePerms; 626 item.BasePermissions = effectivePerms;
587 item.CurrentPermissions = effectivePerms; 627 item.CurrentPermissions = effectivePerms;
588 item.NextPermissions = allObjectsNextOwnerPerms & effectivePerms; 628 item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
589 item.EveryOnePermissions = allObjectsEveryOnePerms & effectivePerms; 629 item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
590 item.GroupPermissions = allObjectsGroupPerms & effectivePerms; 630 item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
591 631
592 item.CurrentPermissions &= 632 item.CurrentPermissions &=
593 ((uint)PermissionMask.Copy | 633 ((uint)PermissionMask.Copy |
@@ -743,7 +783,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
743 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) 783 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
744 { 784 {
745 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 785 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
746 folder = m_Scene.InventoryService.GetFolder(f); 786 if (f != null)
787 folder = m_Scene.InventoryService.GetFolder(f);
747 788
748 if(folder.Type == 14 || folder.Type == 16) 789 if(folder.Type == 14 || folder.Type == 16)
749 { 790 {
@@ -779,16 +820,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
779 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 820 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
780 { 821 {
781// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 822// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
782
783 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 823 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
784 item = m_Scene.InventoryService.GetItem(item); 824 item = m_Scene.InventoryService.GetItem(item);
785 825
786 if (item == null) 826 if (item == null)
787 { 827 {
788 m_log.WarnFormat(
789 "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()",
790 itemID, remoteClient.Name);
791
792 return null; 828 return null;
793 } 829 }
794 830
@@ -856,12 +892,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
856 pos -= bbox / 2; 892 pos -= bbox / 2;
857 } 893 }
858 894
895 int primcount = 0;
896 foreach (SceneObjectGroup g in objlist)
897 primcount += g.PrimCount;
898
899 if (!m_Scene.Permissions.CanRezObject(
900 primcount, remoteClient.AgentId, pos)
901 && !attachment)
902 {
903 // The client operates in no fail mode. It will
904 // have already removed the item from the folder
905 // if it's no copy.
906 // Put it back if it's not an attachment
907 //
908 if (item != null)
909 {
910 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
911 remoteClient.SendBulkUpdateInventory(item);
912 }
913
914 return null;
915 }
916
859 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) 917 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
860 return null; 918 return null;
861 919
862 for (int i = 0; i < objlist.Count; i++) 920 for (int i = 0; i < objlist.Count; i++)
863 { 921 {
864 group = objlist[i]; 922 group = objlist[i];
923 SceneObjectPart rootPart = group.RootPart;
865 924
866// m_log.DebugFormat( 925// m_log.DebugFormat(
867// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", 926// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
@@ -909,7 +968,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
909 968
910 if (attachment) 969 if (attachment)
911 { 970 {
912 group.RootPart.Flags |= PrimFlags.Phantom; 971// group.RootPart.Flags |= PrimFlags.Phantom;
913 group.IsAttachment = true; 972 group.IsAttachment = true;
914 } 973 }
915 974
@@ -919,7 +978,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
919 // one full update during the attachment 978 // one full update during the attachment
920 // process causes some clients to fail to display the 979 // process causes some clients to fail to display the
921 // attachment properly. 980 // attachment properly.
922 m_Scene.AddNewSceneObject(group, !attachment, false); 981 m_Scene.AddNewSceneObject(group, true, false);
923 982
924 // if attachment we set it's asset id so object updates 983 // if attachment we set it's asset id so object updates
925 // can reflect that, if not, we set it's position in world. 984 // can reflect that, if not, we set it's position in world.
@@ -934,8 +993,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
934 993
935 if (!attachment) 994 if (!attachment)
936 { 995 {
937 SceneObjectPart rootPart = group.RootPart;
938
939 if (rootPart.Shape.PCode == (byte)PCode.Prim) 996 if (rootPart.Shape.PCode == (byte)PCode.Prim)
940 group.ClearPartAttachmentData(); 997 group.ClearPartAttachmentData();
941 998
@@ -953,6 +1010,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
953// remoteClient.Name); 1010// remoteClient.Name);
954 } 1011 }
955 1012
1013 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
1014
956 if (item != null) 1015 if (item != null)
957 DoPostRezWhenFromItem(item, attachment); 1016 DoPostRezWhenFromItem(item, attachment);
958 1017
@@ -1033,10 +1092,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1033 // object itself before we rez. 1092 // object itself before we rez.
1034 // 1093 //
1035 // Only do these for the first object if we are rezzing a coalescence. 1094 // Only do these for the first object if we are rezzing a coalescence.
1036 if (i == 0) 1095 // nahh dont mess with coalescence objects,
1096 // the name in inventory can be change for inventory purpuses only
1097 if (objlist.Count == 1)
1037 { 1098 {
1038 rootPart.Name = item.Name; 1099 rootPart.Name = item.Name;
1039 rootPart.Description = item.Description; 1100 rootPart.Description = item.Description;
1101 }
1102
1103 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
1104 {
1040 rootPart.ObjectSaleType = item.SaleType; 1105 rootPart.ObjectSaleType = item.SaleType;
1041 rootPart.SalePrice = item.SalePrice; 1106 rootPart.SalePrice = item.SalePrice;
1042 } 1107 }
@@ -1047,17 +1112,55 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1047// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", 1112// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
1048// rootPart.OwnerID, item.Owner, item.CurrentPermissions); 1113// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
1049 1114
1050 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) 1115 if ((rootPart.OwnerID != item.Owner) ||
1116 (item.CurrentPermissions & 16) != 0 ||
1117 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
1051 { 1118 {
1052 //Need to kill the for sale here 1119 //Need to kill the for sale here
1053 rootPart.ObjectSaleType = 0; 1120 rootPart.ObjectSaleType = 0;
1054 rootPart.SalePrice = 10; 1121 rootPart.SalePrice = 10;
1055 } 1122
1123 if (m_Scene.Permissions.PropagatePermissions())
1124 {
1125 foreach (SceneObjectPart part in so.Parts)
1126 {
1127 part.GroupMask = 0; // DO NOT propagate here
1056 1128
1057 foreach (SceneObjectPart part in so.Parts) 1129 part.LastOwnerID = part.OwnerID;
1130 part.OwnerID = item.Owner;
1131 part.Inventory.ChangeInventoryOwner(item.Owner);
1132 }
1133
1134 so.ApplyNextOwnerPermissions();
1135
1136 // In case the user has changed flags on a received item
1137 // we have to apply those changes after the slam. Else we
1138 // get a net loss of permissions
1139 foreach (SceneObjectPart part in so.Parts)
1140 {
1141 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
1142 {
1143 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1144 part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
1145 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1146 part.NextOwnerMask = item.NextPermissions & part.BaseMask;
1147 }
1148 }
1149 }
1150 }
1151 else
1058 { 1152 {
1059 part.FromUserInventoryItemID = fromUserInventoryItemId; 1153 foreach (SceneObjectPart part in so.Parts)
1060 part.ApplyPermissionsOnRez(item, true, m_Scene); 1154 {
1155 part.FromUserInventoryItemID = fromUserInventoryItemId;
1156
1157 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1158 part.EveryoneMask = item.EveryOnePermissions;
1159 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1160 part.NextOwnerMask = item.NextPermissions;
1161 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
1162 part.GroupMask = item.GroupPermissions;
1163 }
1061 } 1164 }
1062 1165
1063 rootPart.TrimPermissions(); 1166 rootPart.TrimPermissions();
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index 64feec1..93a7cf2 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -205,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
205 m_scene, 205 m_scene,
206 "ScriptEventsPerSecondMonitor", 206 "ScriptEventsPerSecondMonitor",
207 "Script Events", 207 "Script Events",
208 m => m.Scene.StatsReporter.LastReportedSimStats[20], 208 m => m.Scene.StatsReporter.LastReportedSimStats[23],
209 m => string.Format("{0} per second", m.GetValue()))); 209 m => string.Format("{0} per second", m.GetValue())));
210 210
211 m_staticMonitors.Add( 211 m_staticMonitors.Add(
@@ -301,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
301 m_scene, 301 m_scene,
302 "SpareFrameTimeMonitor", 302 "SpareFrameTimeMonitor",
303 "Spare Frame Time", 303 "Spare Frame Time",
304 m => m.Scene.StatsReporter.LastReportedSimStats[21], 304 m => m.Scene.StatsReporter.LastReportedSimStats[38],
305 m => string.Format("{0} ms", m.GetValue()))); 305 m => string.Format("{0} ms", m.GetValue())));
306 306
307 m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); 307 m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 7ecbd26..7d0c47f 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -336,6 +336,102 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
336 } 336 }
337 } 337 }
338 338
339 /// <summary>
340 ///
341 /// </summary>
342 /// <param name="uuid"></param>
343 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
344 /// <returns></returns>
345 private bool TryGetUserNames(UUID uuid, string[] names)
346 {
347 if (names == null)
348 names = new string[2];
349
350 if (TryGetUserNamesFromCache(uuid, names))
351 return true;
352
353 if (TryGetUserNamesFromServices(uuid, names))
354 return true;
355
356 return false;
357 }
358
359 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
360 {
361 lock (m_UserCache)
362 {
363 if (m_UserCache.ContainsKey(uuid))
364 {
365 names[0] = m_UserCache[uuid].FirstName;
366 names[1] = m_UserCache[uuid].LastName;
367
368 return true;
369 }
370 }
371
372 return false;
373 }
374
375 /// <summary>
376 /// Try to get the names bound to the given uuid, from the services.
377 /// </summary>
378 /// <returns>True if the name was found, false if not.</returns>
379 /// <param name='uuid'></param>
380 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
381 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
382 {
383 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
384
385 if (account != null)
386 {
387 names[0] = account.FirstName;
388 names[1] = account.LastName;
389
390 UserData user = new UserData();
391 user.FirstName = account.FirstName;
392 user.LastName = account.LastName;
393
394 lock (m_UserCache)
395 m_UserCache[uuid] = user;
396
397 return true;
398 }
399 else
400 {
401 // Let's try the GridUser service
402 GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
403 if (uInfo != null)
404 {
405 string url, first, last, tmp;
406 UUID u;
407 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
408 {
409 AddUser(uuid, first, last, url);
410
411 if (m_UserCache.ContainsKey(uuid))
412 {
413 names[0] = m_UserCache[uuid].FirstName;
414 names[1] = m_UserCache[uuid].LastName;
415
416 return true;
417 }
418 }
419 else
420 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
421 }
422// else
423// {
424// m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
425// }
426
427 names[0] = "Unknown";
428 names[1] = "UserUMMTGUN9";
429
430 return false;
431 }
432 }
433
434
339 #region IUserManagement 435 #region IUserManagement
340 436
341 public UUID GetUserIdByName(string name) 437 public UUID GetUserIdByName(string name)
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index ea5b34e..a5c7543 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -138,9 +138,9 @@ namespace OpenSim.Region.CoreModules.Hypergrid
138 } 138 }
139 } 139 }
140 140
141 protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 141 protected override List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
142 { 142 {
143 List<MapBlockData> mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 143 List<MapBlockData> mapBlocks = base.GetAndSendBlocksInternal(remoteClient, minX, minY, maxX, maxY, flag);
144 lock (m_SeenMapBlocks) 144 lock (m_SeenMapBlocks)
145 { 145 {
146 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) 146 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 9dfeb96..87f4798 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 *
@@ -108,6 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
108 private Dictionary<UUID, HttpRequestClass> m_pendingRequests; 106 private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
109 private Scene m_scene; 107 private Scene m_scene;
110 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); 108 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
109 public static SmartThreadPool ThreadPool = null;
111 110
112 public HttpRequestModule() 111 public HttpRequestModule()
113 { 112 {
@@ -290,29 +289,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
290 return true; 289 return true;
291 } 290 }
292 291
293 public void StopHttpRequestsForScript(UUID id) 292 public void StopHttpRequest(uint m_localID, UUID m_itemID)
294 { 293 {
295 if (m_pendingRequests != null) 294 if (m_pendingRequests != null)
296 { 295 {
297 List<UUID> keysToRemove = null;
298
299 lock (HttpListLock) 296 lock (HttpListLock)
300 { 297 {
301 foreach (HttpRequestClass req in m_pendingRequests.Values) 298 HttpRequestClass tmpReq;
299 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
302 { 300 {
303 if (req.ItemID == id) 301 tmpReq.Stop();
304 { 302 m_pendingRequests.Remove(m_itemID);
305 req.Stop();
306
307 if (keysToRemove == null)
308 keysToRemove = new List<UUID>();
309
310 keysToRemove.Add(req.ReqID);
311 }
312 } 303 }
313
314 if (keysToRemove != null)
315 keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove));
316 } 304 }
317 } 305 }
318 } 306 }
@@ -330,13 +318,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
330 { 318 {
331 lock (HttpListLock) 319 lock (HttpListLock)
332 { 320 {
333 foreach (HttpRequestClass req in m_pendingRequests.Values) 321 foreach (UUID luid in m_pendingRequests.Keys)
334 { 322 {
335 if (req.Finished) 323 HttpRequestClass tmpReq;
336 return req; 324
325 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
326 {
327 if (tmpReq.Finished)
328 {
329 return tmpReq;
330 }
331 }
337 } 332 }
338 } 333 }
339
340 return null; 334 return null;
341 } 335 }
342 336
@@ -363,9 +357,32 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
363 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 357 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
364 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 358 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
365 359
360
366 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); 361 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
362 int maxThreads = 15;
363
364 IConfig httpConfig = config.Configs["HttpRequestModule"];
365 if (httpConfig != null)
366 {
367 maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
368 }
367 369
368 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 370 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
371
372 // First instance sets this up for all sims
373 if (ThreadPool == null)
374 {
375 STPStartInfo startInfo = new STPStartInfo();
376 startInfo.IdleTimeout = 20000;
377 startInfo.MaxWorkerThreads = maxThreads;
378 startInfo.MinWorkerThreads = 1;
379 startInfo.ThreadPriority = ThreadPriority.BelowNormal;
380 startInfo.StartSuspended = true;
381 startInfo.ThreadPoolName = "ScriptsHttpReq";
382
383 ThreadPool = new SmartThreadPool(startInfo);
384 ThreadPool.Start();
385 }
369 } 386 }
370 387
371 public void AddRegion(Scene scene) 388 public void AddRegion(Scene scene)
@@ -409,8 +426,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
409 426
410 public class HttpRequestClass : IServiceRequest 427 public class HttpRequestClass : IServiceRequest
411 { 428 {
412// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
413
414 // Constants for parameters 429 // Constants for parameters
415 // public const int HTTP_BODY_MAXLENGTH = 2; 430 // public const int HTTP_BODY_MAXLENGTH = 2;
416 // public const int HTTP_METHOD = 0; 431 // public const int HTTP_METHOD = 0;
@@ -437,6 +452,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
437 public string HttpMIMEType = "text/plain;charset=utf-8"; 452 public string HttpMIMEType = "text/plain;charset=utf-8";
438 public int HttpTimeout; 453 public int HttpTimeout;
439 public bool HttpVerifyCert = true; 454 public bool HttpVerifyCert = true;
455 public IWorkItemResult WorkItem = null;
456
440 //public bool HttpVerboseThrottle = true; // not implemented 457 //public bool HttpVerboseThrottle = true; // not implemented
441 public List<string> HttpCustomHeaders = null; 458 public List<string> HttpCustomHeaders = null;
442 public bool HttpPragmaNoCache = true; 459 public bool HttpPragmaNoCache = true;
@@ -484,15 +501,40 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
484 501
485 public void Process() 502 public void Process()
486 { 503 {
504 _finished = false;
505
506 lock (HttpRequestModule.ThreadPool)
507 WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
508 }
509
510 private object StpSendWrapper(object o)
511 {
487 SendRequest(); 512 SendRequest();
513 return null;
488 } 514 }
489 515
516 /*
517 * TODO: More work on the response codes. Right now
518 * returning 200 for success or 499 for exception
519 */
520
490 public void SendRequest() 521 public void SendRequest()
491 { 522 {
523 HttpWebResponse response = null;
524 Stream resStream = null;
525 StringBuilder sb = new StringBuilder();
526 byte[] buf = new byte[8192];
527 string tempString = null;
528 int count = 0;
529
492 try 530 try
493 { 531 {
494 Request = (HttpWebRequest)WebRequest.Create(Url); 532 Request = (HttpWebRequest)WebRequest.Create(Url);
495 Request.AllowAutoRedirect = false; 533 Request.AllowAutoRedirect = false;
534
535 //This works around some buggy HTTP Servers like Lighttpd
536 Request.ServicePoint.Expect100Continue = false;
537
496 Request.Method = HttpMethod; 538 Request.Method = HttpMethod;
497 Request.ContentType = HttpMIMEType; 539 Request.ContentType = HttpMIMEType;
498 540
@@ -500,7 +542,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
500 { 542 {
501 // We could hijack Connection Group Name to identify 543 // We could hijack Connection Group Name to identify
502 // a desired security exception. But at the moment we'll use a dummy header instead. 544 // a desired security exception. But at the moment we'll use a dummy header instead.
503// Request.ConnectionGroupName = "NoVerify";
504 Request.Headers.Add("NoVerifyCert", "true"); 545 Request.Headers.Add("NoVerifyCert", "true");
505 } 546 }
506// else 547// else
@@ -533,14 +574,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
533 } 574 }
534 } 575 }
535 576
536 if (ResponseHeaders != null) 577 foreach (KeyValuePair<string, string> entry in ResponseHeaders)
537 { 578 if (entry.Key.ToLower().Equals("user-agent"))
538 foreach (KeyValuePair<string, string> entry in ResponseHeaders) 579 Request.UserAgent = entry.Value;
539 if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) 580 else
540 ((HttpWebRequest)Request).UserAgent = entry.Value; 581 Request.Headers[entry.Key] = entry.Value;
541 else
542 Request.Headers[entry.Key] = entry.Value;
543 }
544 582
545 // Encode outbound data 583 // Encode outbound data
546 if (!string.IsNullOrEmpty(OutboundBody)) 584 if (!string.IsNullOrEmpty(OutboundBody))
@@ -552,12 +590,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
552 bstream.Write(data, 0, data.Length); 590 bstream.Write(data, 0, data.Length);
553 } 591 }
554 592
593 Request.Timeout = HttpTimeout;
555 try 594 try
556 { 595 {
557 IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); 596 // execute the request
558 597 response = (HttpWebResponse) Request.GetResponse();
559 ThreadPool.RegisterWaitForSingleObject(
560 result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true);
561 } 598 }
562 catch (WebException e) 599 catch (WebException e)
563 { 600 {
@@ -565,63 +602,72 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
565 { 602 {
566 throw; 603 throw;
567 } 604 }
605 response = (HttpWebResponse)e.Response;
606 }
568 607
569 HttpWebResponse response = (HttpWebResponse)e.Response; 608 Status = (int)response.StatusCode;
570 609
571 Status = (int)response.StatusCode; 610 resStream = response.GetResponseStream();
572 ResponseBody = response.StatusDescription;
573 _finished = true;
574 }
575 }
576 catch (Exception e)
577 {
578// m_log.Debug(
579// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e);
580 611
581 Status = (int)OSHttpStatusCode.ClientErrorJoker; 612 do
582 ResponseBody = e.Message; 613 {
583 _finished = true; 614 // fill the buffer with data
584 } 615 count = resStream.Read(buf, 0, buf.Length);
585 }
586 616
587 private void ResponseCallback(IAsyncResult ar) 617 // make sure we read some data
588 { 618 if (count != 0)
589 HttpWebResponse response = null; 619 {
620 // translate from bytes to ASCII text
621 tempString = Util.UTF8.GetString(buf, 0, count);
590 622
591 try 623 // continue building the string
624 sb.Append(tempString);
625 if (sb.Length > 2048)
626 break;
627 }
628 } while (count > 0); // any more data to read?
629
630 ResponseBody = sb.ToString().Replace("\r", "");
631 }
632 catch (WebException e)
592 { 633 {
593 try 634 if (e.Status == WebExceptionStatus.ProtocolError)
594 { 635 {
595 response = (HttpWebResponse)Request.EndGetResponse(ar); 636 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
596 } 637 Status = (int)webRsp.StatusCode;
597 catch (WebException e) 638 try
598 {
599 if (e.Status != WebExceptionStatus.ProtocolError)
600 { 639 {
601 throw; 640 using (Stream responseStream = webRsp.GetResponseStream())
641 {
642 using (StreamReader reader = new StreamReader(responseStream))
643 ResponseBody = reader.ReadToEnd();
644 }
645 }
646 catch
647 {
648 ResponseBody = webRsp.StatusDescription;
602 } 649 }
603 650 }
604 response = (HttpWebResponse)e.Response; 651 else
652 {
653 Status = (int)OSHttpStatusCode.ClientErrorJoker;
654 ResponseBody = e.Message;
605 } 655 }
606 656
607 Status = (int)response.StatusCode; 657 if (ResponseBody == null)
658 ResponseBody = String.Empty;
608 659
609 using (Stream stream = response.GetResponseStream()) 660 _finished = true;
610 { 661 return;
611 StreamReader reader = new StreamReader(stream, Encoding.UTF8);
612 ResponseBody = reader.ReadToEnd();
613 }
614 } 662 }
615 catch (Exception e) 663 catch (Exception e)
616 { 664 {
617 Status = (int)OSHttpStatusCode.ClientErrorJoker; 665 // Don't crash on anything else
618 ResponseBody = e.Message;
619
620// m_log.Debug(
621// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e);
622 } 666 }
623 finally 667 finally
624 { 668 {
669 if (resStream != null)
670 resStream.Close();
625 if (response != null) 671 if (response != null)
626 response.Close(); 672 response.Close();
627 673
@@ -672,20 +718,25 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
672 _finished = true; 718 _finished = true;
673 } 719 }
674 } 720 }
675 }
676 721
677 private void TimeoutCallback(object state, bool timedOut) 722 if (ResponseBody == null)
678 { 723 ResponseBody = String.Empty;
679 if (timedOut) 724
680 Request.Abort(); 725 _finished = true;
681 } 726 }
682 727
683 public void Stop() 728 public void Stop()
684 { 729 {
685// m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); 730 try
686 731 {
687 if (Request != null) 732 if (!WorkItem.Cancel())
688 Request.Abort(); 733 {
734 WorkItem.Cancel(true);
735 }
736 }
737 catch (Exception)
738 {
739 }
689 } 740 }
690 } 741 }
691} \ No newline at end of file 742}
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 99a3122..a21931c 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()
@@ -229,8 +211,10 @@ 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() + "/";
@@ -240,9 +224,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
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 }
@@ -275,8 +259,10 @@ 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() + "/";
@@ -286,9 +272,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
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,46 @@ 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
583 {
584 Hashtable headers = (Hashtable)request["headers"];
577 585
578 int pos1 = uri.IndexOf("/");// /lslhttp 586// string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/";
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
587 pathInfo = uri.Substring(pos3); 588 int pos1 = uri.IndexOf("/");// /lslhttp
589 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
590 int pos3 = uri.IndexOf("/", pos2 + 1); // /lslhttp/urlcode
588 591
589 UrlData urlData = null; 592 string uri_tmp = uri.Substring(0, pos3 + 1);
593 //HTTP server code doesn't provide us with QueryStrings
594 string pathInfo;
595 string queryString;
596 queryString = "";
590 597
591 lock (m_UrlMap) 598 pathInfo = uri.Substring(pos3);
592 {
593 string url;
594 599
595 if (is_ssl) 600 UrlData url = null;
596 url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; 601 string urlkey;
602 if (!is_ssl)
603 urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
604 //m_UrlMap[];
597 else 605 else
598 url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; 606 urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
599 607
600 // Avoid a race - the request URL may have been released via llRequestUrl() whilst this 608 if (m_UrlMap.ContainsKey(urlkey))
601 // request was being processed. 609 {
602 if (!m_UrlMap.TryGetValue(url, out urlData)) 610 url = m_UrlMap[urlkey];
611 }
612 else
613 {
614 //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString());
603 return; 615 return;
616 }
604 617
605 //for llGetHttpHeader support we need to store original URI here 618 //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 619 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
@@ -611,6 +624,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
611 requestData.requestDone = false; 624 requestData.requestDone = false;
612 requestData.startTime = System.Environment.TickCount; 625 requestData.startTime = System.Environment.TickCount;
613 requestData.uri = uri; 626 requestData.uri = uri;
627 requestData.hostID = url.hostID;
628 requestData.scene = url.scene;
614 if (requestData.headers == null) 629 if (requestData.headers == null)
615 requestData.headers = new Dictionary<string, string>(); 630 requestData.headers = new Dictionary<string, string>();
616 631
@@ -619,8 +634,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
619 string key = (string)header.Key; 634 string key = (string)header.Key;
620 string value = (string)header.Value; 635 string value = (string)header.Value;
621 requestData.headers.Add(key, value); 636 requestData.headers.Add(key, value);
637 if (key == "cookie")
638 {
639 string[] parts = value.Split(new char[] {'='});
640 if (parts[0] == "agni_sl_session_id" && parts.Length > 1)
641 {
642 string cookie = Uri.UnescapeDataString(parts[1]);
643 string[] crumbs = cookie.Split(new char[] {':'});
644 UUID owner;
645 if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner))
646 {
647 if (crumbs[1].Length == 32)
648 {
649 Scene scene = requestData.scene;
650 if (scene != null)
651 {
652 SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID);
653 if (host != null)
654 {
655 if (host.OwnerID == owner)
656 requestData.allowResponseType = true;
657 }
658 }
659 }
660 }
661 }
662 }
622 } 663 }
623
624 foreach (DictionaryEntry de in request) 664 foreach (DictionaryEntry de in request)
625 { 665 {
626 if (de.Key.ToString() == "querystringkeys") 666 if (de.Key.ToString() == "querystringkeys")
@@ -631,13 +671,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
631 if (request.ContainsKey(key)) 671 if (request.ContainsKey(key))
632 { 672 {
633 string val = (String)request[key]; 673 string val = (String)request[key];
634 queryString = queryString + key + "=" + val + "&"; 674 if (key != "")
675 {
676 queryString = queryString + key + "=" + val + "&";
677 }
678 else
679 {
680 queryString = queryString + val + "&";
681 }
635 } 682 }
636 } 683 }
637
638 if (queryString.Length > 1) 684 if (queryString.Length > 1)
639 queryString = queryString.Substring(0, queryString.Length - 1); 685 queryString = queryString.Substring(0, queryString.Length - 1);
686
640 } 687 }
688
641 } 689 }
642 690
643 //if this machine is behind DNAT/port forwarding, currently this is being 691 //if this machine is behind DNAT/port forwarding, currently this is being
@@ -645,23 +693,34 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
645 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; 693 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
646 requestData.headers["x-path-info"] = pathInfo; 694 requestData.headers["x-path-info"] = pathInfo;
647 requestData.headers["x-query-string"] = queryString; 695 requestData.headers["x-query-string"] = queryString;
648 requestData.headers["x-script-url"] = urlData.url; 696 requestData.headers["x-script-url"] = url.url;
649 697
650 urlData.requests.Add(requestID, requestData); 698 //requestData.ev = new ManualResetEvent(false);
651 m_RequestMap.Add(requestID, urlData); 699 lock (url.requests)
652 } 700 {
701 url.requests.Add(requestID, requestData);
702 }
703 lock (m_RequestMap)
704 {
705 //add to request map
706 m_RequestMap.Add(requestID, url);
707 }
653 708
654 urlData.engine.PostScriptEvent( 709 url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
655 urlData.itemID, 710
656 "http_request", 711 //send initial response?
657 new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); 712// Hashtable response = new Hashtable();
658 } 713
659 catch (Exception we) 714 return;
660 { 715
661 //Hashtable response = new Hashtable(); 716 }
662 m_log.Warn("[HttpRequestHandler]: http-in request failed"); 717 catch (Exception we)
663 m_log.Warn(we.Message); 718 {
664 m_log.Warn(we.StackTrace); 719 //Hashtable response = new Hashtable();
720 m_log.Warn("[HttpRequestHandler]: http-in request failed");
721 m_log.Warn(we.Message);
722 m_log.Warn(we.StackTrace);
723 }
665 } 724 }
666 } 725 }
667 726
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 3484387..1a53a8b 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,61 +368,58 @@ 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)
370 string name, UUID id, string msg)
371 { 372 {
373 if (channel == DEBUG_CHANNEL)
374 return true;
375
372 // Is id an avatar? 376 // Is id an avatar?
373 ScenePresence sp = m_scene.GetScenePresence(target); 377 ScenePresence sp = m_scene.GetScenePresence(target);
374 378
375 if (sp != null) 379 if (sp != null)
376 { 380 {
377 // ignore if a child agent this is restricted to inside one 381 // Send message to avatar
378 // region 382 if (channel == 0)
379 if (sp.IsChildAgent)
380 return;
381
382 // Channel zero only goes to the avatar
383 // non zero channel messages only go to the attachments of the avatar.
384 if (channel != 0)
385 { 383 {
386 List<SceneObjectGroup> attachments = sp.GetAttachments(); 384 // Channel 0 goes to viewer ONLY
387 if (attachments.Count == 0) 385 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
388 return; 386 return true;
387 }
389 388
390 // Get uuid of attachments 389 List<SceneObjectGroup> attachments = sp.GetAttachments();
391 List<UUID> targets = new List<UUID>();
392 foreach (SceneObjectGroup sog in attachments)
393 {
394 if (!sog.IsDeleted)
395 targets.Add(sog.UUID);
396 }
397 390
398 // Need to check each attachment 391 if (attachments.Count == 0)
399 foreach (ListenerInfo li 392 return true;
400 in m_listenerManager.GetListeners(UUID.Zero,
401 channel, name, id, msg))
402 {
403 if (li.GetHostID().Equals(id))
404 continue;
405 393
406 if (m_scene.GetSceneObjectPart( 394 // Get uuid of attachments
407 li.GetHostID()) == null) 395 List<UUID> targets = new List<UUID>();
408 { 396 foreach (SceneObjectGroup sog in attachments)
409 continue; 397 {
410 } 398 if (!sog.IsDeleted)
399 targets.Add(sog.UUID);
400 }
411 401
412 if (targets.Contains(li.GetHostID())) 402 // Need to check each attachment
413 QueueMessage(new ListenerInfo(li, name, id, msg)); 403 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
414 } 404 {
405 if (li.GetHostID().Equals(id))
406 continue;
407
408 if (m_scene.GetSceneObjectPart(li.GetHostID()) == null)
409 continue;
410
411 if (targets.Contains(li.GetHostID()))
412 QueueMessage(new ListenerInfo(li, name, id, msg));
415 } 413 }
416 414
417 return; 415 return true;
418 } 416 }
419 417
420 // No avatar found so look for an object 418 SceneObjectPart part = m_scene.GetSceneObjectPart(target);
421 foreach (ListenerInfo li 419 if (part == null) // Not even an object
422 in m_listenerManager.GetListeners(UUID.Zero, channel, 420 return true; // No error
423 name, id, msg)) 421
422 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
424 { 423 {
425 // Dont process if this message is from yourself! 424 // Dont process if this message is from yourself!
426 if (li.GetHostID().Equals(id)) 425 if (li.GetHostID().Equals(id))
@@ -438,7 +437,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
438 } 437 }
439 } 438 }
440 439
441 return; 440 return true;
442 } 441 }
443 442
444 protected void QueueMessage(ListenerInfo li) 443 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/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 1f782f5..e585c25 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -201,13 +201,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
201 uint regionX = Util.WorldToRegionLoc((uint)x); 201 uint regionX = Util.WorldToRegionLoc((uint)x);
202 uint regionY = Util.WorldToRegionLoc((uint)y); 202 uint regionY = Util.WorldToRegionLoc((uint)y);
203 203
204 // Sanity check
205 if ((Util.RegionToWorldLoc(regionX) != (uint)x) || (Util.RegionToWorldLoc(regionY) != (uint)y))
206 {
207 m_log.WarnFormat("{0} GetRegionByPosition. Bad position requested: not the base of the region. Requested Pos=<{1},{2}>, Should Be=<{3},{4}>",
208 LogHeader, x, y, Util.RegionToWorldLoc(regionX), Util.RegionToWorldLoc(regionY));
209 }
210
211 // First see if it's a neighbour, even if it isn't on this sim. 204 // First see if it's a neighbour, even if it isn't on this sim.
212 // Neighbour data is cached in memory, so this is fast 205 // Neighbour data is cached in memory, so this is fast
213 206
@@ -218,9 +211,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
218 region = rcache.GetRegionByPosition(x, y); 211 region = rcache.GetRegionByPosition(x, y);
219 if (region != null) 212 if (region != null)
220 { 213 {
221 m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>", 214 //m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>",
222 LogHeader, region.RegionName, rcache.RegionName, 215 // LogHeader, region.RegionName, rcache.RegionName,
223 Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); 216 // Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
224 break; 217 break;
225 } 218 }
226 } 219 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
index ae76288..2961c10 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
@@ -81,22 +81,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
81 { 81 {
82 return new List<GridRegion>(m_neighbours.Values); 82 return new List<GridRegion>(m_neighbours.Values);
83 } 83 }
84 84
85 // Get a region given its base coordinates (in meters).
86 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
87 // be the base coordinate of the region.
88 // The snapping is technically unnecessary but is harmless because regions are always
89 // multiples of the legacy region size (256).
90 public GridRegion GetRegionByPosition(int x, int y) 85 public GridRegion GetRegionByPosition(int x, int y)
91 { 86 {
92 uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize; 87 // do actual search by position
93 uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize; 88 // not the best, but this will not hold that many regions
94 ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap); 89 GridRegion foundRegion = null;
95 90 foreach(GridRegion r in m_neighbours.Values)
96 if (m_neighbours.ContainsKey(handle)) 91 {
97 return m_neighbours[handle]; 92 if (x >= r.RegionLocX && x < r.RegionLocX + r.RegionSizeX
98 93 && y >= r.RegionLocY && y < r.RegionLocY + r.RegionSizeY)
99 return null; 94 {
95 foundRegion = r;
96 break;
97 }
98 }
99
100 return foundRegion;
100 } 101 }
101 } 102 }
102} 103}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 25ae689..c33f7f5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -198,4 +198,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
198 Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected"); 198 Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected");
199 } 199 }
200 } 200 }
201} \ No newline at end of file 201}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 08d6bdd..ef0eec5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
53 /// </remarks> 53 /// </remarks>
54 54
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")]
56
56 public class MapImageServiceModule : IMapImageUploadModule, ISharedRegionModule 57 public class MapImageServiceModule : IMapImageUploadModule, ISharedRegionModule
57 { 58 {
58 private static readonly ILog m_log = 59 private static readonly ILog m_log =
@@ -93,9 +94,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
93 if (config == null) 94 if (config == null)
94 return; 95 return;
95 96
96 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); 97 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime", "60"));
97
98 // if refresh is less than zero, disable the module
99 if (refreshminutes < 0) 98 if (refreshminutes < 0)
100 { 99 {
101 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Negative refresh time given in config. Module disabled."); 100 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Negative refresh time given in config. Module disabled.");
@@ -128,6 +127,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
128 m_refreshTimer.Interval = m_refreshtime; 127 m_refreshTimer.Interval = m_refreshtime;
129 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); 128 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
130 129
130
131 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0} min and service object {1}", 131 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0} min and service object {1}",
132 refreshminutes, service); 132 refreshminutes, service);
133 } 133 }
@@ -218,7 +218,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
218 // If the region/maptile is legacy sized, just upload the one tile like it has always been done 218 // If the region/maptile is legacy sized, just upload the one tile like it has always been done
219 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize) 219 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
220 { 220 {
221 ConvertAndUploadMaptile(mapTile, 221 ConvertAndUploadMaptile(scene, mapTile,
222 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, 222 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
223 scene.RegionInfo.RegionName); 223 scene.RegionInfo.RegionName);
224 } 224 }
@@ -240,7 +240,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
240 (int)Constants.RegionSize, (int)Constants.RegionSize); 240 (int)Constants.RegionSize, (int)Constants.RegionSize);
241 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat)) 241 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
242 { 242 {
243 ConvertAndUploadMaptile(subMapTile, 243 ConvertAndUploadMaptile(scene, subMapTile,
244 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize), 244 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
245 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize), 245 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize),
246 scene.Name); 246 scene.Name);
@@ -253,8 +253,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
253 ///<summary> 253 ///<summary>
254 /// 254 ///
255 ///</summary> 255 ///</summary>
256 private void UploadMapTile(IScene scene) 256 public void UploadMapTile(IScene scene)
257 { 257 {
258 m_log.DebugFormat("{0}: upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
259
258 // Create a JPG map tile and upload it to the AddMapTile API 260 // Create a JPG map tile and upload it to the AddMapTile API
259 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>(); 261 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
260 if (tileGenerator == null) 262 if (tileGenerator == null)
@@ -265,18 +267,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
265 267
266 using (Bitmap mapTile = tileGenerator.CreateMapTile()) 268 using (Bitmap mapTile = tileGenerator.CreateMapTile())
267 { 269 {
268 if (mapTile != null) 270 // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
269 { 271 // is no static map tile.
270 UploadMapTile(scene, mapTile); 272 if (mapTile == null)
271 } 273 return;
272 else 274
273 { 275 UploadMapTile(scene, mapTile);
274 m_log.WarnFormat("{0} Tile image generation failed", LogHeader);
275 }
276 } 276 }
277 } 277 }
278 278
279 private void ConvertAndUploadMaptile(Image tileImage, uint locX, uint locY, string regionName) 279 private void ConvertAndUploadMaptile(IScene scene, Image tileImage, uint locX, uint locY, string regionName)
280 { 280 {
281 byte[] jpgData = Utils.EmptyBytes; 281 byte[] jpgData = Utils.EmptyBytes;
282 282
@@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
288 if (jpgData != Utils.EmptyBytes) 288 if (jpgData != Utils.EmptyBytes)
289 { 289 {
290 string reason = string.Empty; 290 string reason = string.Empty;
291 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, out reason)) 291 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, scene.RegionInfo.ScopeID, out reason))
292 { 292 {
293 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader, 293 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
294 regionName, locX, locY, reason); 294 regionName, locX, locY, reason);
@@ -300,4 +300,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
300 } 300 }
301 } 301 }
302 } 302 }
303} \ No newline at end of file 303}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index cc8203e..3755650 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
185 * Agent-related communications 185 * Agent-related communications
186 */ 186 */
187 187
188 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 188 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason)
189 { 189 {
190 if (destination == null) 190 if (destination == null)
191 { 191 {
@@ -204,7 +204,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
204 return false; 204 return false;
205 } 205 }
206 206
207 public bool UpdateAgent(GridRegion destination, AgentData cAgentData) 207 public bool UpdateAgent(GridRegion destination, AgentData cAgentData, EntityTransferContext ctx)
208 { 208 {
209 if (destination == null) 209 if (destination == null)
210 return false; 210 return false;
@@ -268,6 +268,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
268 268
269 } 269 }
270 270
271
271 return m_scenes[destination.RegionID].QueryAccess(agentID, agentHomeURI, viaTeleport, position, features, out reason); 272 return m_scenes[destination.RegionID].QueryAccess(agentID, agentHomeURI, viaTeleport, position, features, out reason);
272 } 273 }
273 274
@@ -305,7 +306,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
305 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token); 306 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
306 return true; 307 return true;
307 } 308 }
308
309 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 309 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
310 return false; 310 return false;
311 } 311 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 1e095ca..0ebdbce 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -160,7 +160,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
160 * Agent-related communications 160 * Agent-related communications
161 */ 161 */
162 162
163 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 163 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason)
164 { 164 {
165 if (destination == null) 165 if (destination == null)
166 { 166 {
@@ -170,27 +170,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
170 } 170 }
171 171
172 // Try local first 172 // Try local first
173 if (m_localBackend.CreateAgent(source, destination, aCircuit, teleportFlags, out reason)) 173 if (m_localBackend.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason))
174 return true; 174 return true;
175 175
176 // else do the remote thing 176 // else do the remote thing
177 if (!m_localBackend.IsLocalRegion(destination.RegionID)) 177 if (!m_localBackend.IsLocalRegion(destination.RegionID))
178 { 178 {
179 return m_remoteConnector.CreateAgent(source, destination, aCircuit, teleportFlags, out reason); 179 return m_remoteConnector.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason);
180 } 180 }
181 return false; 181 return false;
182 } 182 }
183 183
184 public bool UpdateAgent(GridRegion destination, AgentData cAgentData) 184 public bool UpdateAgent(GridRegion destination, AgentData cAgentData, EntityTransferContext ctx)
185 { 185 {
186 if (destination == null) 186 if (destination == null)
187 return false; 187 return false;
188 188
189 // Try local first 189 // Try local first
190 if (m_localBackend.IsLocalRegion(destination.RegionID)) 190 if (m_localBackend.IsLocalRegion(destination.RegionID))
191 return m_localBackend.UpdateAgent(destination, cAgentData); 191 return m_localBackend.UpdateAgent(destination, cAgentData, ctx);
192 192
193 return m_remoteConnector.UpdateAgent(destination, cAgentData); 193 return m_remoteConnector.UpdateAgent(destination, cAgentData, ctx);
194 } 194 }
195 195
196 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) 196 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
@@ -236,7 +236,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
236 return false; 236 return false;
237 } 237 }
238 238
239
240 public bool CloseAgent(GridRegion destination, UUID id, string auth_token) 239 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
241 { 240 {
242 if (destination == null) 241 if (destination == null)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 6d4ac39..cf9a7b4 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);
@@ -203,4 +209,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
203 209
204 #endregion 210 #endregion
205 } 211 }
206} \ No newline at end of file 212}
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 ed52e48..53610d9 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
@@ -97,5 +97,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
97 97
98 return null; 98 return null;
99 } 99 }
100
101 public void Remove(string name)
102 {
103 if (!m_NameCache.Contains(name))
104 return;
105
106 UUID uuid = UUID.Zero;
107 if (m_NameCache.TryGetValue(name, out uuid))
108 {
109 m_NameCache.Remove(name);
110 m_UUIDCache.Remove(uuid);
111 }
112 }
100 } 113 }
101} 114}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 9c6706f..406f4a8 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -160,10 +160,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
160 160
161 private IAssetService m_assetService = null; 161 private IAssetService m_assetService = null;
162 162
163
164 private UUID m_defaultUser; 163 private UUID m_defaultUser;
165 164
166 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string,object>options) 165 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
167 { 166 {
168 m_rootScene = scene; 167 m_rootScene = scene;
169 168
@@ -172,7 +171,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
172 m_defaultUser = (UUID)options["default-user"]; 171 m_defaultUser = (UUID)options["default-user"];
173 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString()); 172 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString());
174 } 173 }
175 else 174 else
176 { 175 {
177 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 176 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
178 } 177 }
@@ -189,8 +188,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
189 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 188 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
190 m_log.Error(e); 189 m_log.Error(e);
191 } 190 }
192 191
193 m_errorMessage = String.Empty; 192 m_errorMessage = String.Empty;
193
194 m_merge = options.ContainsKey("merge"); 194 m_merge = options.ContainsKey("merge");
195 m_forceTerrain = options.ContainsKey("force-terrain"); 195 m_forceTerrain = options.ContainsKey("force-terrain");
196 m_forceParcels = options.ContainsKey("force-parcels"); 196 m_forceParcels = options.ContainsKey("force-parcels");
@@ -199,10 +199,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
199 m_requestId = requestId; 199 m_requestId = requestId;
200 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; 200 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
201 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; 201 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
202 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"] 202 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
203 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f); 203 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
204 204
205 // Zero can never be a valid user or group id 205 // Zero can never be a valid user id (or group)
206 m_validUserUuids[UUID.Zero] = false; 206 m_validUserUuids[UUID.Zero] = false;
207 m_validGroupUuids[UUID.Zero] = false; 207 m_validGroupUuids[UUID.Zero] = false;
208 208
@@ -210,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
210 m_assetService = m_rootScene.AssetService; 210 m_assetService = m_rootScene.AssetService;
211 } 211 }
212 212
213 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object>options) 213 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options)
214 { 214 {
215 m_rootScene = scene; 215 m_rootScene = scene;
216 m_loadPath = null; 216 m_loadPath = null;
@@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
220 m_requestId = requestId; 220 m_requestId = requestId;
221 221
222 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 222 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
223 223
224 // Zero can never be a valid user id 224 // Zero can never be a valid user id
225 m_validUserUuids[UUID.Zero] = false; 225 m_validUserUuids[UUID.Zero] = false;
226 226
@@ -523,7 +523,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
523 } 523 }
524 } 524 }
525 525
526
527 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); 526 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
528 527
529 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 528 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
@@ -600,6 +599,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
600 // being no copy/no mod for everyone 599 // being no copy/no mod for everyone
601 lock (part.TaskInventory) 600 lock (part.TaskInventory)
602 { 601 {
602 // And zap any troublesome sit target information
603 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
604 part.SitTargetPosition = new Vector3(0, 0, 0);
605
606 // Fix ownership/creator of inventory items
607 // Not doing so results in inventory items
608 // being no copy/no mod for everyone
609 part.TaskInventory.LockItemsForRead(true);
610
603 TaskInventoryDictionary inv = part.TaskInventory; 611 TaskInventoryDictionary inv = part.TaskInventory;
604 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 612 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
605 { 613 {
@@ -620,11 +628,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
620 if (!ResolveGroupUuid(kvp.Value.GroupID)) 628 if (!ResolveGroupUuid(kvp.Value.GroupID))
621 kvp.Value.GroupID = UUID.Zero; 629 kvp.Value.GroupID = UUID.Zero;
622 } 630 }
631 part.TaskInventory.LockItemsForRead(false);
632
623 } 633 }
624 } 634 }
625 } 635 }
626 636
627
628 /// <summary> 637 /// <summary>
629 /// Load serialized parcels. 638 /// Load serialized parcels.
630 /// </summary> 639 /// </summary>
@@ -645,7 +654,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
645 parcel.AABBMin += parcelDisp; 654 parcel.AABBMin += parcelDisp;
646 parcel.AABBMax += parcelDisp; 655 parcel.AABBMax += parcelDisp;
647 } 656 }
648 657
649 // Validate User and Group UUID's 658 // Validate User and Group UUID's
650 659
651 if (!ResolveGroupUuid(parcel.GroupID)) 660 if (!ResolveGroupUuid(parcel.GroupID))
@@ -660,14 +669,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
660 } 669 }
661 else 670 else
662 { 671 {
663 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; 672 parcel.OwnerID = m_defaultUser;
673 parcel.GroupID = UUID.Zero;
664 parcel.IsGroupOwned = false; 674 parcel.IsGroupOwned = false;
665 } 675 }
666 } 676 }
667 else 677 else
668 { 678 {
669 if (!ResolveUserUuid(scene, parcel.OwnerID)) 679 if (!ResolveUserUuid(scene, parcel.OwnerID))
670 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; 680 parcel.OwnerID = m_defaultUser;
681
682 if (!ResolveGroupUuid(parcel.GroupID))
683 parcel.GroupID = UUID.Zero;
671 } 684 }
672 685
673 List<LandAccessEntry> accessList = new List<LandAccessEntry>(); 686 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
@@ -918,7 +931,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
918 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) 931 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
919 { 932 {
920 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); 933 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
921
922 using (MemoryStream ms = new MemoryStream(data)) 934 using (MemoryStream ms = new MemoryStream(data))
923 { 935 {
924 if (m_displacement != Vector3.Zero || m_rotation != 0f) 936 if (m_displacement != Vector3.Zero || m_rotation != 0f)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 6a09caf..4178a57 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -111,17 +111,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
111 String defaultUser = ""; 111 String defaultUser = "";
112 float rotation = 0f; 112 float rotation = 0f;
113 Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0); 113 Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0);
114 114
115
115 OptionSet options = new OptionSet(); 116 OptionSet options = new OptionSet();
116 options.Add("m|merge", delegate (string v) { mergeOar = (v != null); }); 117 options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
117 options.Add("s|skip-assets", delegate (string v) { skipAssets = (v != null); }); 118 options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); });
118 options.Add("force-terrain", delegate (string v) { forceTerrain = (v != null); }); 119 options.Add("force-terrain", delegate(string v) { forceTerrain = (v != null); });
119 options.Add("forceterrain", delegate (string v) { forceTerrain = (v != null); }); // downward compatibility 120 options.Add("forceterrain", delegate(string v) { forceTerrain = (v != null); }); // downward compatibility
120 options.Add("force-parcels", delegate (string v) { forceParcels = (v != null); }); 121 options.Add("force-parcels", delegate(string v) { forceParcels = (v != null); });
121 options.Add("forceparcels", delegate (string v) { forceParcels = (v != null); }); // downward compatibility 122 options.Add("forceparcels", delegate(string v) { forceParcels = (v != null); }); // downward compatibility
122 options.Add("no-objects", delegate (string v) { noObjects = (v != null); }); 123 options.Add("no-objects", delegate(string v) { noObjects = (v != null); });
123 options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; }); 124 options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; });
124 options.Add("displacement=", delegate (string v) { 125 options.Add("displacement=", delegate(string v)
126 {
125 try 127 try
126 { 128 {
127 displacement = v == null ? Vector3.Zero : Vector3.Parse(v); 129 displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
@@ -148,7 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
148 // Convert to radians for internals 150 // Convert to radians for internals
149 rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI; 151 rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI;
150 }); 152 });
151 options.Add("rotation-center=", delegate (string v) { 153 options.Add("rotation-center=", delegate(string v)
154 {
152 try 155 try
153 { 156 {
154 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v); 157 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
@@ -288,12 +291,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
288 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 291 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
289 DearchiveRegion(loadPath, Guid.Empty, archiveOptions); 292 DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
290 } 293 }
291 294
292 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options) 295 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options)
293 { 296 {
294 m_log.InfoFormat( 297 m_log.InfoFormat(
295 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath); 298 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
296 299
297 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion(); 300 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
298 } 301 }
299 302
@@ -302,7 +305,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
302 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 305 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
303 DearchiveRegion(loadStream, Guid.Empty, archiveOptions); 306 DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
304 } 307 }
305
306 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options) 308 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
307 { 309 {
308 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion(); 310 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index db66c83..895b55d 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 80fa08a..3ded00c 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -68,6 +68,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
68 public event ChangeDelegate OnEstateInfoChange; 68 public event ChangeDelegate OnEstateInfoChange;
69 public event MessageDelegate OnEstateMessage; 69 public event MessageDelegate OnEstateMessage;
70 70
71 private int m_delayCount = 0;
72
71 #region Region Module interface 73 #region Region Module interface
72 74
73 public string Name { get { return "EstateManagementModule"; } } 75 public string Name { get { return "EstateManagementModule"; } }
@@ -95,6 +97,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
95 97
96 m_commands = new EstateManagementCommands(this); 98 m_commands = new EstateManagementCommands(this);
97 m_commands.Initialise(); 99 m_commands.Initialise();
100
101 m_regionChangeTimer.Interval = 10000;
102 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
103 m_regionChangeTimer.AutoReset = false;
98 } 104 }
99 105
100 public void RemoveRegion(Scene scene) {} 106 public void RemoveRegion(Scene scene) {}
@@ -142,6 +148,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
142 flags |= RegionFlags.AllowParcelChanges; 148 flags |= RegionFlags.AllowParcelChanges;
143 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) 149 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
144 flags |= RegionFlags.BlockParcelSearch; 150 flags |= RegionFlags.BlockParcelSearch;
151 if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
152 flags |= (RegionFlags)(1 << 11);
153 if (Scene.RegionInfo.RegionSettings.Casino)
154 flags |= (RegionFlags)(1 << 10);
145 155
146 if (Scene.RegionInfo.RegionSettings.FixedSun) 156 if (Scene.RegionInfo.RegionSettings.FixedSun)
147 flags |= RegionFlags.SunFixed; 157 flags |= RegionFlags.SunFixed;
@@ -194,6 +204,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
194 change(Scene.RegionInfo.RegionID); 204 change(Scene.RegionInfo.RegionID);
195 } 205 }
196 206
207 protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e)
208 {
209 ChangeDelegate change = OnRegionInfoChange;
210
211 if (change != null)
212 change(Scene.RegionInfo.RegionID);
213 }
214
197 public void TriggerRegionInfoChange() 215 public void TriggerRegionInfoChange()
198 { 216 {
199 m_regionChangeTimer.Stop(); 217 m_regionChangeTimer.Stop();
@@ -587,6 +605,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
587 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 605 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
588 if (restartModule != null) 606 if (restartModule != null)
589 { 607 {
608 if (timeInSeconds == -1)
609 {
610 m_delayCount++;
611 if (m_delayCount > 3)
612 return;
613
614 restartModule.DelayRestart(3600, "Restart delayed by region manager");
615 return;
616 }
617
590 List<int> times = new List<int>(); 618 List<int> times = new List<int>();
591 while (timeInSeconds > 0) 619 while (timeInSeconds > 0)
592 { 620 {
@@ -1477,7 +1505,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
1477 sendRegionHandshake(client); 1505 sendRegionHandshake(client);
1478 } 1506 }
1479 1507
1480 private uint GetEstateFlags() 1508
1509 public uint GetEstateFlags()
1481 { 1510 {
1482 RegionFlags flags = RegionFlags.None; 1511 RegionFlags flags = RegionFlags.None;
1483 1512
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 73c592d..378826d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -40,23 +40,33 @@ namespace OpenSim.Region.CoreModules.World.Land
40 //Land types set with flags in ParcelOverlay. 40 //Land types set with flags in ParcelOverlay.
41 //Only one of these can be used. 41 //Only one of these can be used.
42 public const float BAN_LINE_SAFETY_HIEGHT = 100; 42 public const float BAN_LINE_SAFETY_HIEGHT = 100;
43 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000
44 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000
45 43
46 //RequestResults (I think these are right, they seem to work): 44 //RequestResults (I think these are right, they seem to work):
47 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land 45 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
48 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land 46 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
49 47
50 //ParcelSelectObjects 48 //ParcelSelectObjects
49 public const int LAND_SELECT_OBJECTS_OWNER = 2;
51 public const int LAND_SELECT_OBJECTS_GROUP = 4; 50 public const int LAND_SELECT_OBJECTS_GROUP = 4;
52 public const int LAND_SELECT_OBJECTS_OTHER = 8; 51 public const int LAND_SELECT_OBJECTS_OTHER = 8;
53 public const int LAND_SELECT_OBJECTS_OWNER = 2; 52
54 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 53
55 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 54 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
56 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 55 // types 1 to 7 are exclusive
57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 56 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
57 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
59 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 59 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
60 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
61 public const byte LAND_TYPE_unused6 = 6;
62 public const byte LAND_TYPE_unused7 = 7;
63 // next are flags
64 public const byte LAND_FLAG_unused8 = 0x08; // this may become excluside in future
65 public const byte LAND_FLAG_HIDEAVATARS = 0x10;
66 public const byte LAND_FLAG_LOCALSOUND = 0x20;
67 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 0x40; //Equals 01000000
68 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 0x80; //Equals 10000000
69
60 70
61 //These are other constants. Yay! 71 //These are other constants. Yay!
62 public const int START_LAND_LOCAL_ID = 1; 72 public const int START_LAND_LOCAL_ID = 1;
@@ -203,7 +213,13 @@ namespace OpenSim.Region.CoreModules.World.Land
203 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); 213 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
204 } 214 }
205 } 215 }
206 216 public void sendClientInitialLandInfo(IClientAPI remoteClient)
217 {
218 if (m_landManagementModule != null)
219 {
220 m_landManagementModule.sendClientInitialLandInfo(remoteClient);
221 }
222 }
207 #endregion 223 #endregion
208 } 224 }
209} 225}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 92f6c1b..ad6793f 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -69,6 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// <summary> 69 /// <summary>
70 /// Minimum land unit size in region co-ordinates. 70 /// Minimum land unit size in region co-ordinates.
71 /// </summary> 71 /// </summary>
72
72 public const int LandUnit = 4; 73 public const int LandUnit = 4;
73 74
74 private static readonly string remoteParcelRequestPath = "0009/"; 75 private static readonly string remoteParcelRequestPath = "0009/";
@@ -89,21 +90,26 @@ namespace OpenSim.Region.CoreModules.World.Land
89 /// <value> 90 /// <value>
90 /// Land objects keyed by local id 91 /// Land objects keyed by local id
91 /// </value> 92 /// </value>
92 private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); 93// private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
94
95 //ubit: removed the readonly so i can move it around
96 private Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
93 97
94 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 98 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
95 99
96 private bool m_allowedForcefulBans = true; 100 private bool m_allowedForcefulBans = true;
101 private UUID DefaultGodParcelGroup;
102 private string DefaultGodParcelName;
97 103
98 // caches ExtendedLandData 104 // caches ExtendedLandData
99 private Cache parcelInfoCache; 105 private Cache parcelInfoCache;
100 106
101
102 /// <summary> 107 /// <summary>
103 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. 108 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
104 /// </summary> 109 /// </summary>
105 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>(); 110 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
106 111
112
107 // Enables limiting parcel layer info transmission when doing simple updates 113 // Enables limiting parcel layer info transmission when doing simple updates
108 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } 114 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
109 // "View distance" for sending parcel layer info if asked for from a view point in the region 115 // "View distance" for sending parcel layer info if asked for from a view point in the region
@@ -125,6 +131,8 @@ namespace OpenSim.Region.CoreModules.World.Land
125 { 131 {
126 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); 132 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
127 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); 133 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
134 DefaultGodParcelGroup = new UUID(landManagementConfig.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
135 DefaultGodParcelName = landManagementConfig.GetString("DefaultAdministratorParcelName", "Default Parcel");
128 } 136 }
129 } 137 }
130 138
@@ -132,6 +140,7 @@ namespace OpenSim.Region.CoreModules.World.Land
132 { 140 {
133 m_scene = scene; 141 m_scene = scene;
134 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; 142 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
143
135 landChannel = new LandChannel(scene, this); 144 landChannel = new LandChannel(scene, this);
136 145
137 parcelInfoCache = new Cache(); 146 parcelInfoCache = new Cache();
@@ -154,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Land
154 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 163 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
155 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 164 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
156 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 165 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
157 166
158 lock (m_scene) 167 lock (m_scene)
159 { 168 {
160 m_scene.LandChannel = (ILandChannel)landChannel; 169 m_scene.LandChannel = (ILandChannel)landChannel;
@@ -204,13 +213,14 @@ namespace OpenSim.Region.CoreModules.World.Land
204 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 213 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
205 client.OnSetStartLocationRequest += ClientOnSetHome; 214 client.OnSetStartLocationRequest += ClientOnSetHome;
206 215
207 216/* avatar is still a child here position is unknown
208 EntityBase presenceEntity; 217 EntityBase presenceEntity;
209 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 218 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
210 { 219 {
211 SendLandUpdate((ScenePresence)presenceEntity, true); 220 SendLandUpdate((ScenePresence)presenceEntity, true);
212 SendParcelOverlay(client); 221 SendParcelOverlay(client);
213 } 222 }
223*/
214 } 224 }
215 225
216 public void EventMakeChildAgent(ScenePresence avatar) 226 public void EventMakeChildAgent(ScenePresence avatar)
@@ -220,48 +230,6 @@ namespace OpenSim.Region.CoreModules.World.Land
220 230
221 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 231 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
222 { 232 {
223 //If we are forcing a position for them to go
224 if (forcedPosition.ContainsKey(remoteClient.AgentId))
225 {
226 ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
227
228 //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
229 //When the avatar walks into a ban line on the ground, it prevents getting stuck
230 agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
231
232 //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
233 if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2)
234 {
235// m_log.DebugFormat(
236// "[LAND MANAGEMENT MODULE]: Stopping force position of {0} because {1} is close enough to {2}",
237// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);
238
239 forcedPosition.Remove(remoteClient.AgentId);
240 }
241 //if we are far away, teleport
242 else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3)
243 {
244 Vector3 forcePosition = forcedPosition[remoteClient.AgentId];
245// m_log.DebugFormat(
246// "[LAND MANAGEMENT MODULE]: Teleporting out {0} because {1} is too far from avatar position {2}",
247// clientAvatar.Name, clientAvatar.AbsolutePosition, forcePosition);
248
249 m_scene.RequestTeleportLocation(remoteClient, m_scene.RegionInfo.RegionHandle,
250 forcePosition, clientAvatar.Lookat, (uint)Constants.TeleportFlags.ForceRedirect);
251
252 forcedPosition.Remove(remoteClient.AgentId);
253 }
254 else
255 {
256// m_log.DebugFormat(
257// "[LAND MANAGEMENT MODULE]: Forcing {0} from {1} to {2}",
258// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);
259
260 //Forces them toward the forced position we want if they aren't there yet
261 agentData.UseClientAgentPosition = true;
262 agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId];
263 }
264 }
265 } 233 }
266 234
267 public void Close() 235 public void Close()
@@ -314,6 +282,7 @@ namespace OpenSim.Region.CoreModules.World.Land
314 { 282 {
315 m_landList.Clear(); 283 m_landList.Clear();
316 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 284 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
285
317 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; 286 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
318 } 287 }
319 } 288 }
@@ -324,16 +293,16 @@ namespace OpenSim.Region.CoreModules.World.Land
324 /// <returns>The parcel created.</returns> 293 /// <returns>The parcel created.</returns>
325 protected ILandObject CreateDefaultParcel() 294 protected ILandObject CreateDefaultParcel()
326 { 295 {
327 m_log.DebugFormat( 296 m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName);
328 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); 297
329 298 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
330 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 299
331 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, 300 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
332 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); 301 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
333 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 302 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
334 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 303 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
335 304
336 return AddLandObject(fullSimParcel); 305 return AddLandObject(fullSimParcel);
337 } 306 }
338 307
339 public List<ILandObject> AllParcels() 308 public List<ILandObject> AllParcels()
@@ -382,10 +351,17 @@ namespace OpenSim.Region.CoreModules.World.Land
382 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 351 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
383 { 352 {
384 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 353 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
385 if (position.HasValue) 354
386 { 355 if (!position.HasValue)
387 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; 356 return;
388 } 357
358// land should have no word on avatar physics
359// bool isFlying = avatar.PhysicsActor.Flying;
360// avatar.RemoveFromPhysicalScene();
361
362 avatar.AbsolutePosition = (Vector3)position;
363
364// avatar.AddToPhysicalScene(isFlying);
389 } 365 }
390 366
391 public void SendYouAreRestrictedNotice(ScenePresence avatar) 367 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -405,36 +381,14 @@ namespace OpenSim.Region.CoreModules.World.Land
405 } 381 }
406 382
407 if (parcelAvatarIsEntering != null) 383 if (parcelAvatarIsEntering != null)
408 { 384 EnforceBans(parcelAvatarIsEntering, avatar);
409 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
410 {
411 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
412 {
413 SendYouAreBannedNotice(avatar);
414 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
415 }
416 else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
417 {
418 SendYouAreRestrictedNotice(avatar);
419 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
420 }
421 else
422 {
423 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
424 }
425 }
426 else
427 {
428 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
429 }
430 }
431 } 385 }
432 } 386 }
433 387
434 public void SendOutNearestBanLine(IClientAPI client) 388 public void SendOutNearestBanLine(IClientAPI client)
435 { 389 {
436 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 390 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
437 if (sp == null || sp.IsChildAgent) 391 if (sp == null)
438 return; 392 return;
439 393
440 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); 394 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition);
@@ -454,32 +408,44 @@ namespace OpenSim.Region.CoreModules.World.Land
454 return; 408 return;
455 } 409 }
456 410
411 public void sendClientInitialLandInfo(IClientAPI remoteClient)
412 {
413 ScenePresence avatar;
414
415 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar))
416 return;
417
418
419 if (!avatar.IsChildAgent)
420 {
421 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
422 if (over == null)
423 return;
424
425 avatar.currentParcelUUID = over.LandData.GlobalID;
426 over.SendLandUpdateToClient(avatar.ControllingClient);
427 }
428 SendParcelOverlay(remoteClient);
429 }
430
457 public void SendLandUpdate(ScenePresence avatar, bool force) 431 public void SendLandUpdate(ScenePresence avatar, bool force)
458 { 432 {
459 ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 433 if (avatar.IsChildAgent)
460 (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); 434 return;
435
436 ILandObject over = GetLandObjectClipedXY(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
461 437
462 if (over != null) 438 if (over != null)
463 { 439 {
464 if (force) 440 bool NotsameID = (avatar.currentParcelUUID != over.LandData.GlobalID);
465 { 441 if (force || NotsameID)
466 if (!avatar.IsChildAgent)
467 {
468 over.SendLandUpdateToClient(avatar.ControllingClient);
469 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
470 m_scene.RegionInfo.RegionID);
471 }
472 }
473
474 if (avatar.currentParcelUUID != over.LandData.GlobalID)
475 { 442 {
476 if (!avatar.IsChildAgent) 443 over.SendLandUpdateToClient(avatar.ControllingClient);
477 { 444// sl doesnt seem to send this now, as it used 2
478 over.SendLandUpdateToClient(avatar.ControllingClient); 445// SendParcelOverlay(avatar.ControllingClient);
479 avatar.currentParcelUUID = over.LandData.GlobalID; 446 avatar.currentParcelUUID = over.LandData.GlobalID;
480 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, 447 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
481 m_scene.RegionInfo.RegionID); 448 m_scene.RegionInfo.RegionID);
482 }
483 } 449 }
484 } 450 }
485 } 451 }
@@ -531,6 +497,7 @@ namespace OpenSim.Region.CoreModules.World.Land
531 //when we are finally in a safe place, lets release the forced position lock 497 //when we are finally in a safe place, lets release the forced position lock
532 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); 498 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
533 } 499 }
500 EnforceBans(parcel, clientAvatar);
534 } 501 }
535 } 502 }
536 503
@@ -589,7 +556,7 @@ namespace OpenSim.Region.CoreModules.World.Land
589 requiredPowers = GroupPowers.LandManageBanned; 556 requiredPowers = GroupPowers.LandManageBanned;
590 557
591 if (m_scene.Permissions.CanEditParcelProperties(agentID, 558 if (m_scene.Permissions.CanEditParcelProperties(agentID,
592 land, requiredPowers)) 559 land, requiredPowers, false))
593 { 560 {
594 land.UpdateAccessList(flags, transactionID, sequenceID, 561 land.UpdateAccessList(flags, transactionID, sequenceID,
595 sections, entries, remote_client); 562 sections, entries, remote_client);
@@ -623,14 +590,11 @@ namespace OpenSim.Region.CoreModules.World.Land
623 new_land.LandData.LocalID = newLandLocalID; 590 new_land.LandData.LocalID = newLandLocalID;
624 591
625 bool[,] landBitmap = new_land.GetLandBitmap(); 592 bool[,] landBitmap = new_land.GetLandBitmap();
626 // m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). newLocalID={3}",
627 // LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), newLandLocalID);
628
629 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1)) 593 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
630 { 594 {
631 // Going to variable sized regions can cause mismatches 595 // Going to variable sized regions can cause mismatches
632 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})", 596 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
633 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1) ); 597 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1));
634 } 598 }
635 else 599 else
636 { 600 {
@@ -652,7 +616,7 @@ namespace OpenSim.Region.CoreModules.World.Land
652 { 616 {
653 m_log.ErrorFormat( 617 m_log.ErrorFormat(
654 "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}", 618 "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}",
655 LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y, 619 LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y,
656 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); 620 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name);
657 621
658 return null; 622 return null;
@@ -668,10 +632,10 @@ namespace OpenSim.Region.CoreModules.World.Land
668 { 632 {
669 if (landBitmap[x, y]) 633 if (landBitmap[x, y])
670 { 634 {
671 // m_log.DebugFormat( 635 // m_log.DebugFormat(
672 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", 636 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
673 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); 637 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
674 638
675 m_landIDList[x, y] = newLandLocalID; 639 m_landIDList[x, y] = newLandLocalID;
676 } 640 }
677 } 641 }
@@ -723,27 +687,28 @@ namespace OpenSim.Region.CoreModules.World.Land
723 /// </summary> 687 /// </summary>
724 public void Clear(bool setupDefaultParcel) 688 public void Clear(bool setupDefaultParcel)
725 { 689 {
726 List<ILandObject> parcels; 690 Dictionary<int, ILandObject> landworkList;
691 // move to work pointer since we are deleting it all
727 lock (m_landList) 692 lock (m_landList)
728 { 693 {
729 parcels = new List<ILandObject>(m_landList.Values); 694 landworkList = m_landList;
695 m_landList = new Dictionary<int, ILandObject>();
730 } 696 }
731 697
732 foreach (ILandObject lo in parcels) 698 // this 2 methods have locks (now)
699 ResetSimLandObjects();
700
701 if (setupDefaultParcel)
702 CreateDefaultParcel();
703
704 // fire outside events unlocked
705 foreach (ILandObject lo in landworkList.Values)
733 { 706 {
734 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); 707 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID);
735 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); 708 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID);
736 } 709 }
710 landworkList.Clear();
737 711
738 lock (m_landList)
739 {
740 m_landList.Clear();
741
742 ResetSimLandObjects();
743 }
744
745 if (setupDefaultParcel)
746 CreateDefaultParcel();
747 } 712 }
748 713
749 private void performFinalLandJoin(ILandObject master, ILandObject slave) 714 private void performFinalLandJoin(ILandObject master, ILandObject slave)
@@ -787,58 +752,37 @@ namespace OpenSim.Region.CoreModules.World.Land
787 /// <returns>Land object at the point supplied</returns> 752 /// <returns>Land object at the point supplied</returns>
788 public ILandObject GetLandObject(float x_float, float y_float) 753 public ILandObject GetLandObject(float x_float, float y_float)
789 { 754 {
790 return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */); 755 return GetLandObject((int)x_float, (int)y_float, true);
791 /* 756 }
792 int x;
793 int y;
794
795 if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
796 return null;
797 757
798 try 758 // if x,y is off region this will return the parcel at cliped x,y
799 { 759 // as did code it replaces
800 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); 760 public ILandObject GetLandObjectClipedXY(float x, float y)
801 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); 761 {
802 } 762 //do clip inline
803 catch (OverflowException) 763 int avx = (int)x;
804 { 764 if (avx < 0)
805 return null; 765 avx = 0;
806 } 766 else if (avx >= m_scene.RegionInfo.RegionSizeX)
767 avx = (int)Constants.RegionSize - 1;
807 768
808 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) 769 int avy = (int)y;
809 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) 770 if (avy < 0)
810 || x < 0 771 avy = 0;
811 || y < 0) 772 else if (avy >= m_scene.RegionInfo.RegionSizeY)
812 { 773 avy = (int)Constants.RegionSize - 1;
813 return null;
814 }
815 774
816 lock (m_landList) 775 lock (m_landIDList)
817 { 776 {
818 // Corner case. If an autoreturn happens during sim startup
819 // we will come here with the list uninitialized
820 //
821// int landId = m_landIDList[x, y];
822
823// if (landId == 0)
824// m_log.DebugFormat(
825// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
826// x, y, m_scene.RegionInfo.RegionName);
827
828 try 777 try
829 { 778 {
830 if (m_landList.ContainsKey(m_landIDList[x, y])) 779 return m_landList[m_landIDList[avx / LandUnit, avy / LandUnit]];
831 return m_landList[m_landIDList[x, y]];
832 } 780 }
833 catch (Exception e) 781 catch (IndexOutOfRangeException)
834 { 782 {
835 m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})", 783 return null;
836 LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
837 } 784 }
838
839 return null;
840 } 785 }
841 */
842 } 786 }
843 787
844 // Public entry. 788 // Public entry.
@@ -848,30 +792,28 @@ namespace OpenSim.Region.CoreModules.World.Land
848 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); 792 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
849 } 793 }
850 794
851 /// <summary> 795 public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
852 /// Given a region position, return the parcel land object for that location
853 /// </summary>
854 /// <returns>
855 /// The land object.
856 /// </returns>
857 /// <param name='x'></param>
858 /// <param name='y'></param>
859 /// <param name='returnNullIfLandObjectNotFound'>
860 /// Return null if the land object requested is not within the region's bounds.
861 /// </param>
862 private ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
863 { 796 {
864 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) 797 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
865 { 798 {
866 // These exceptions here will cause a lot of complaints from the users specifically because 799 // These exceptions here will cause a lot of complaints from the users specifically because
867 // they happen every time at border crossings 800 // they happen every time at border crossings
868 if (returnNullIfLandObjectOutsideBounds) 801 if (returnNullIfLandObjectOutsideBounds)
869 return null; 802 return null;
870 else 803 else
871 throw new Exception( 804 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
872 String.Format("{0} GetLandObject for non-existent position. Region={1}, pos=<{2},{3}", 805 }
873 LogHeader, m_scene.RegionInfo.RegionName, x, y) 806
874 ); 807 lock (m_landIDList)
808 {
809 try
810 {
811 return m_landList[m_landIDList[x / 4, y / 4]];
812 }
813 catch (IndexOutOfRangeException)
814 {
815 return null;
816 }
875 } 817 }
876 818
877 return m_landList[m_landIDList[x / 4, y / 4]]; 819 return m_landList[m_landIDList[x / 4, y / 4]];
@@ -1033,7 +975,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1033 975
1034 //If we are still here, then they are subdividing within one piece of land 976 //If we are still here, then they are subdividing within one piece of land
1035 //Check owner 977 //Check owner
1036 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin)) 978 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin, true))
1037 { 979 {
1038 return; 980 return;
1039 } 981 }
@@ -1043,6 +985,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1043 newLand.LandData.Name = newLand.LandData.Name; 985 newLand.LandData.Name = newLand.LandData.Name;
1044 newLand.LandData.GlobalID = UUID.Random(); 986 newLand.LandData.GlobalID = UUID.Random();
1045 newLand.LandData.Dwell = 0; 987 newLand.LandData.Dwell = 0;
988 // Clear "Show in search" on the cut out parcel to prevent double-charging
989 newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory;
1046 990
1047 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 991 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
1048 992
@@ -1058,11 +1002,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1058 //Now add the new land object 1002 //Now add the new land object
1059 ILandObject result = AddLandObject(newLand); 1003 ILandObject result = AddLandObject(newLand);
1060 1004
1061 if (result != null) 1005 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
1062 { 1006 result.SendLandUpdateToAvatarsOverMe();
1063 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); 1007 startLandObject.SendLandUpdateToAvatarsOverMe();
1064 result.SendLandUpdateToAvatarsOverMe(); 1008 m_scene.ForEachClient(SendParcelOverlay);
1065 } 1009
1066 } 1010 }
1067 1011
1068 /// <summary> 1012 /// <summary>
@@ -1104,7 +1048,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1104 { 1048 {
1105 return; 1049 return;
1106 } 1050 }
1107 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin)) 1051 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin, true))
1108 { 1052 {
1109 return; 1053 return;
1110 } 1054 }
@@ -1127,6 +1071,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1127 } 1071 }
1128 1072
1129 masterLandObject.SendLandUpdateToAvatarsOverMe(); 1073 masterLandObject.SendLandUpdateToAvatarsOverMe();
1074 m_scene.ForEachClient(SendParcelOverlay);
1130 } 1075 }
1131 1076
1132 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) 1077 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
@@ -1143,12 +1088,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1143 1088
1144 #region Parcel Updating 1089 #region Parcel Updating
1145 1090
1146 // Send parcel layer info for the whole region
1147 public void SendParcelOverlay(IClientAPI remote_client)
1148 {
1149 SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize);
1150 }
1151
1152 /// <summary> 1091 /// <summary>
1153 /// Send the parcel overlay blocks to the client. We send the overlay packets 1092 /// Send the parcel overlay blocks to the client. We send the overlay packets
1154 /// around a location and limited by the 'parcelLayerViewDistance'. This number 1093 /// around a location and limited by the 'parcelLayerViewDistance'. This number
@@ -1162,145 +1101,116 @@ namespace OpenSim.Region.CoreModules.World.Land
1162 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> 1101 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param>
1163 /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param> 1102 /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param>
1164 /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param> 1103 /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param>
1165 private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance) 1104 public void SendParcelOverlay(IClientAPI remote_client)
1166 { 1105 {
1106 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
1107 return;
1108
1167 const int LAND_BLOCKS_PER_PACKET = 1024; 1109 const int LAND_BLOCKS_PER_PACKET = 1024;
1168 1110
1169 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1111 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1170 int byteArrayCount = 0; 1112 int byteArrayCount = 0;
1171 int sequenceID = 0; 1113 int sequenceID = 0;
1172 1114
1173 int xLow = 0; 1115 // Layer data is in LandUnit (4m) chunks
1174 int xHigh = (int)m_scene.RegionInfo.RegionSizeX; 1116 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += LandUnit)
1175 int yLow = 0;
1176 int yHigh = (int)m_scene.RegionInfo.RegionSizeY;
1177
1178 if (shouldLimitParcelLayerInfoToViewDistance)
1179 { 1117 {
1180 // Compute view distance around the given point 1118 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += LandUnit)
1181 int txLow = xPlace - layerViewDistance;
1182 int txHigh = xPlace + layerViewDistance;
1183 // If the distance is outside the region area, move the view distance to ba all in the region
1184 if (txLow < xLow)
1185 {
1186 txLow = xLow;
1187 txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh);
1188 }
1189 if (txHigh > xHigh)
1190 { 1119 {
1191 txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); 1120 byte tempByte = 0; //This represents the byte for the current 4x4
1192 txHigh = xHigh;
1193 }
1194 xLow = txLow;
1195 xHigh = txHigh;
1196 1121
1197 int tyLow = yPlace - layerViewDistance; 1122 ILandObject currentParcelBlock = GetLandObject(x, y);
1198 int tyHigh = yPlace + layerViewDistance;
1199 if (tyLow < yLow)
1200 {
1201 tyLow = yLow;
1202 tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh);
1203 }
1204 if (tyHigh > yHigh)
1205 {
1206 tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2));
1207 tyHigh = yHigh;
1208 }
1209 yLow = tyLow;
1210 yHigh = tyHigh;
1211 }
1212 // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>",
1213 // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh);
1214 1123
1215 // Layer data is in landUnit (4m) chunks 1124 if (currentParcelBlock != null)
1216 for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1217 {
1218 for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
1219 {
1220 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client);
1221 byteArrayCount++;
1222 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1223 { 1125 {
1224 // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); 1126 // types
1225 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1127 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1226 byteArrayCount = 0; 1128 {
1227 sequenceID++; 1129 //Owner Flag
1228 byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1130 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER;
1229 } 1131 }
1132 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1133 {
1134 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP;
1135 }
1136 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1137 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1138 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1139 {
1140 //Sale type
1141 tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE;
1142 }
1143 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1144 {
1145 //Public type
1146 tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero
1147 }
1148 // LAND_TYPE_IS_BEING_AUCTIONED still unsuported
1149 else
1150 {
1151 //Other Flag
1152 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER;
1153 }
1230 1154
1231 } 1155 // now flags
1232 } 1156 // border control
1233 1157
1234 if (byteArrayCount != 0) 1158 ILandObject westParcel = null;
1235 { 1159 ILandObject southParcel = null;
1236 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1160 if (x > 0)
1237 // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); 1161 {
1238 } 1162 westParcel = GetLandObject((x - 1), y);
1239 } 1163 }
1164 if (y > 0)
1165 {
1166 southParcel = GetLandObject(x, (y - 1));
1167 }
1240 1168
1241 private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client) 1169 if (x == 0)
1242 { 1170 {
1243 byte tempByte = 0; //This represents the byte for the current 4x4 1171 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1172 }
1173 else if (westParcel != null && westParcel != currentParcelBlock)
1174 {
1175 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1176 }
1244 1177
1245 if (currentParcelBlock != null) 1178 if (y == 0)
1246 { 1179 {
1247 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1180 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1248 { 1181 }
1249 //Owner Flag 1182 else if (southParcel != null && southParcel != currentParcelBlock)
1250 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1183 {
1251 } 1184 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1252 else if (currentParcelBlock.LandData.SalePrice > 0 && 1185 }
1253 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1254 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1255 {
1256 //Sale Flag
1257 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1258 }
1259 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1260 {
1261 //Public Flag
1262 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1263 }
1264 else
1265 {
1266 //Other Flag
1267 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1268 }
1269 1186
1270 //Now for border control 1187 // local sound
1188 if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0)
1189 tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND;
1271 1190
1272 ILandObject westParcel = null; 1191 // hide avatars
1273 ILandObject southParcel = null; 1192 if (!currentParcelBlock.LandData.SeeAVs)
1274 if (x > 0) 1193 tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS;
1275 {
1276 westParcel = GetLandObject((x - 1) * LandUnit, y * LandUnit);
1277 }
1278 if (y > 0)
1279 {
1280 southParcel = GetLandObject(x * LandUnit, (y - 1) * LandUnit);
1281 }
1282 1194
1283 if (x == 0)
1284 {
1285 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1286 }
1287 else if (westParcel != null && westParcel != currentParcelBlock)
1288 {
1289 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1290 }
1291 1195
1292 if (y == 0) 1196 byteArray[byteArrayCount] = tempByte;
1293 { 1197 byteArrayCount++;
1294 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1198 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1295 } 1199 {
1296 else if (southParcel != null && southParcel != currentParcelBlock) 1200 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1297 { 1201 byteArrayCount = 0;
1298 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1202 sequenceID++;
1203 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1204 }
1205 }
1299 } 1206 }
1300 1207
1301 } 1208 }
1302 1209
1303 return tempByte; 1210 if (byteArrayCount > 0)
1211 {
1212 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1213 }
1304 } 1214 }
1305 1215
1306 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, 1216 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
@@ -1320,8 +1230,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1320 { 1230 {
1321 if (!temp.Contains(currentParcel)) 1231 if (!temp.Contains(currentParcel))
1322 { 1232 {
1323 currentParcel.ForceUpdateLandInfo(); 1233 if (!currentParcel.IsEitherBannedOrRestricted(remote_client.AgentId))
1324 temp.Add(currentParcel); 1234 {
1235 currentParcel.ForceUpdateLandInfo();
1236 temp.Add(currentParcel);
1237 }
1325 } 1238 }
1326 } 1239 }
1327 } 1240 }
@@ -1338,8 +1251,45 @@ namespace OpenSim.Region.CoreModules.World.Land
1338 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 1251 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
1339 } 1252 }
1340 1253
1341 // Also send the layer data around the point of interest 1254// SendParcelOverlay(remote_client);
1342 SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); 1255 }
1256
1257 public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client)
1258 {
1259 bool snap_selection = false;
1260 bool needOverlay = false;
1261 if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay))
1262 {
1263 //the proprieties to who changed them
1264 ScenePresence av = m_scene.GetScenePresence(remote_client.AgentId);
1265 if(av.IsChildAgent || land != GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y))
1266 land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, remote_client);
1267 else
1268 land.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, remote_client);
1269
1270 UUID parcelID = land.LandData.GlobalID;
1271 m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
1272 {
1273 if (avatar.IsDeleted || avatar.isNPC)
1274 return;
1275
1276 IClientAPI client = avatar.ControllingClient;
1277 if (needOverlay)
1278 SendParcelOverlay(client);
1279
1280 if (avatar.IsChildAgent)
1281 return;
1282
1283 ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
1284 if (aland != null)
1285 {
1286 if (client != remote_client && land == aland)
1287 aland.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, client);
1288 }
1289 if (avatar.currentParcelUUID == parcelID)
1290 avatar.currentParcelUUID = parcelID; // force parcel flags review
1291 });
1292 }
1343 } 1293 }
1344 1294
1345 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) 1295 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
@@ -1352,7 +1302,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1352 1302
1353 if (land != null) 1303 if (land != null)
1354 { 1304 {
1355 land.UpdateLandProperties(args, remote_client); 1305 UpdateLandProperties(land, args, remote_client);
1356 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); 1306 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client);
1357 } 1307 }
1358 } 1308 }
@@ -1408,7 +1358,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1408 land.LandData.GroupID = UUID.Zero; 1358 land.LandData.GroupID = UUID.Zero;
1409 land.LandData.IsGroupOwned = false; 1359 land.LandData.IsGroupOwned = false;
1410 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1360 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1411
1412 m_scene.ForEachClient(SendParcelOverlay); 1361 m_scene.ForEachClient(SendParcelOverlay);
1413 land.SendLandUpdateToClient(true, remote_client); 1362 land.SendLandUpdateToClient(true, remote_client);
1414 UpdateLandObject(land.LandData.LocalID, land.LandData); 1363 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1459,7 +1408,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1459 land.LandData.SalePrice = 0; 1408 land.LandData.SalePrice = 0;
1460 land.LandData.AuthBuyerID = UUID.Zero; 1409 land.LandData.AuthBuyerID = UUID.Zero;
1461 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1410 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1462
1463 m_scene.ForEachClient(SendParcelOverlay); 1411 m_scene.ForEachClient(SendParcelOverlay);
1464 land.SendLandUpdateToClient(true, remote_client); 1412 land.SendLandUpdateToClient(true, remote_client);
1465 UpdateLandObject(land.LandData.LocalID, land.LandData); 1413 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1545,17 +1493,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1545 1493
1546 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1494 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1547 { 1495 {
1548// m_log.DebugFormat(
1549// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name);
1550
1551 // Prevent race conditions from any auto-creation of new parcels for varregions whilst we are still loading
1552 // the existing parcels.
1553 lock (m_landList) 1496 lock (m_landList)
1554 { 1497 {
1555 for (int i = 0; i < data.Count; i++) 1498 for (int i = 0; i < data.Count; i++)
1556 IncomingLandObjectFromStorage(data[i]); 1499 IncomingLandObjectFromStorage(data[i]);
1557 1500
1558 // Layer data is in landUnit (4m) chunks 1501 // Layer data is in LandUnit (4m) chunks
1559 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) 1502 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1560 { 1503 {
1561 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) 1504 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
@@ -1565,7 +1508,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1565 if (m_landList.Count == 1) 1508 if (m_landList.Count == 1)
1566 { 1509 {
1567 m_log.DebugFormat( 1510 m_log.DebugFormat(
1568 "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}", 1511 "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}",
1569 LogHeader, x, y, m_scene.Name); 1512 LogHeader, x, y, m_scene.Name);
1570 1513
1571 int onlyParcelID = 0; 1514 int onlyParcelID = 0;
@@ -1588,11 +1531,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1588 else if (m_landList.Count > 1) 1531 else if (m_landList.Count > 1)
1589 { 1532 {
1590 m_log.DebugFormat( 1533 m_log.DebugFormat(
1591 "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}", 1534 "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}",
1592 LogHeader, x, y, m_scene.Name); 1535 LogHeader, x, y, m_scene.Name);
1593 1536
1594 // There are several other parcels so we must create a new one for the unassigned space 1537 // There are several other parcels so we must create a new one for the unassigned space
1595 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); 1538 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
1596 // Claim all the unclaimed "0" ids 1539 // Claim all the unclaimed "0" ids
1597 newLand.SetLandBitmap(CreateBitmapForID(0)); 1540 newLand.SetLandBitmap(CreateBitmapForID(0));
1598 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 1541 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
@@ -1603,7 +1546,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1603 { 1546 {
1604 // We should never reach this point as the separate code path when no land data exists should have fired instead. 1547 // We should never reach this point as the separate code path when no land data exists should have fired instead.
1605 m_log.WarnFormat( 1548 m_log.WarnFormat(
1606 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", 1549 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present",
1607 LogHeader, m_scene.Name); 1550 LogHeader, m_scene.Name);
1608 } 1551 }
1609 } 1552 }
@@ -1614,9 +1557,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1614 1557
1615 private void IncomingLandObjectFromStorage(LandData data) 1558 private void IncomingLandObjectFromStorage(LandData data)
1616 { 1559 {
1617 ILandObject new_land = new LandObject(data, m_scene); 1560 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1561 new_land.LandData = data.Copy();
1562
1618 new_land.SetLandBitmapFromByteArray(); 1563 new_land.SetLandBitmapFromByteArray();
1619 AddLandObject(new_land); 1564 AddLandObject(new_land);
1565// new_land.SendLandUpdateToAvatarsOverMe();
1620 } 1566 }
1621 1567
1622 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1568 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1773,6 +1719,19 @@ namespace OpenSim.Region.CoreModules.World.Land
1773 land_update.ObscureMusic = properties.ObscureMusic; 1719 land_update.ObscureMusic = properties.ObscureMusic;
1774 land_update.ObscureMedia = properties.ObscureMedia; 1720 land_update.ObscureMedia = properties.ObscureMedia;
1775 1721
1722 if (args.ContainsKey("see_avs"))
1723 {
1724 land_update.SeeAVs = args["see_avs"].AsBoolean();
1725 land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean();
1726 land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean();
1727 }
1728 else
1729 {
1730 land_update.SeeAVs = true;
1731 land_update.AnyAVSounds = true;
1732 land_update.GroupAVSounds = true;
1733 }
1734
1776 ILandObject land; 1735 ILandObject land;
1777 lock (m_landList) 1736 lock (m_landList)
1778 { 1737 {
@@ -1781,13 +1740,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1781 1740
1782 if (land != null) 1741 if (land != null)
1783 { 1742 {
1784 land.UpdateLandProperties(land_update, client); 1743 UpdateLandProperties(land,land_update, client);
1785 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); 1744 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client);
1786 } 1745 }
1787 else 1746 else
1788 { 1747 {
1789 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); 1748 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
1790 } 1749 }
1750
1791 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1751 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1792 } 1752 }
1793 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the 1753 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
@@ -1940,14 +1900,93 @@ namespace OpenSim.Region.CoreModules.World.Land
1940 1900
1941 if (land == null) return; 1901 if (land == null) return;
1942 1902
1943 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions)) 1903 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions, false))
1944 return; 1904 return;
1945 1905
1946 land.LandData.OtherCleanTime = otherCleanTime; 1906 land.LandData.OtherCleanTime = otherCleanTime;
1947 1907
1948 UpdateLandObject(localID, land.LandData); 1908 UpdateLandObject(localID, land.LandData);
1949 } 1909 }
1950 1910
1911 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1912 {
1913 ILandObject land = null;
1914 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1915 foreach (ILandObject landObject in Land)
1916 {
1917 if (landObject.LandData.LocalID == landID)
1918 {
1919 land = landObject;
1920 }
1921 }
1922 land.DeedToGroup(DefaultGodParcelGroup);
1923 land.LandData.Name = DefaultGodParcelName;
1924 land.SendLandUpdateToAvatarsOverMe();
1925 }
1926
1927 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1928 {
1929 ScenePresence SP;
1930 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1931 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1932 if (SP.UserLevel != 0)
1933 {
1934 if (flags == 0) //All parcels, scripted or not
1935 {
1936 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1937 {
1938 if (e.OwnerID == targetID)
1939 {
1940 returns.Add(e);
1941 }
1942 }
1943 );
1944 }
1945 if (flags == 4) //All parcels, scripted object
1946 {
1947 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1948 {
1949 if (e.OwnerID == targetID)
1950 {
1951 if (e.ContainsScripts())
1952 {
1953 returns.Add(e);
1954 }
1955 }
1956 }
1957 );
1958 }
1959 if (flags == 4) //not target parcel, scripted object
1960 {
1961 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1962 {
1963 if (e.OwnerID == targetID)
1964 {
1965 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1966 if (landobject.LandData.OwnerID != e.OwnerID)
1967 {
1968 if (e.ContainsScripts())
1969 {
1970 returns.Add(e);
1971 }
1972 }
1973 }
1974 }
1975 );
1976 }
1977 foreach (SceneObjectGroup ol in returns)
1978 {
1979 ReturnObject(ol, client);
1980 }
1981 }
1982 }
1983 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1984 {
1985 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1986 objs[0] = obj;
1987 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1988 }
1989
1951 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); 1990 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1952 1991
1953 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 1992 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
@@ -1961,7 +2000,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1961 if (targetAvatar.UserLevel == 0) 2000 if (targetAvatar.UserLevel == 0)
1962 { 2001 {
1963 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 2002 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1964 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze)) 2003 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true))
1965 return; 2004 return;
1966 if (flags == 0) 2005 if (flags == 0)
1967 { 2006 {
@@ -1983,7 +2022,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1983 } 2022 }
1984 } 2023 }
1985 } 2024 }
1986
1987 private void OnEndParcelFrozen(object avatar) 2025 private void OnEndParcelFrozen(object avatar)
1988 { 2026 {
1989 ScenePresence targetAvatar = (ScenePresence)avatar; 2027 ScenePresence targetAvatar = (ScenePresence)avatar;
@@ -1994,6 +2032,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1994 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false); 2032 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1995 } 2033 }
1996 2034
2035
1997 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 2036 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1998 { 2037 {
1999 ScenePresence targetAvatar = null; 2038 ScenePresence targetAvatar = null;
@@ -2010,15 +2049,16 @@ namespace OpenSim.Region.CoreModules.World.Land
2010 2049
2011 // Check if you even have permission to do this 2050 // Check if you even have permission to do this
2012 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 2051 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
2013 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) && 2052 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true) &&
2014 !m_scene.Permissions.IsAdministrator(client.AgentId)) 2053 !m_scene.Permissions.IsAdministrator(client.AgentId))
2015 return; 2054 return;
2055
2016 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); 2056 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
2017 2057
2018 targetAvatar.TeleportWithMomentum(pos, null); 2058 targetAvatar.TeleportWithMomentum(pos, null);
2019 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); 2059 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
2020 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); 2060 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
2021 2061
2022 if ((flags & 1) != 0) // Ban TODO: Remove magic number 2062 if ((flags & 1) != 0) // Ban TODO: Remove magic number
2023 { 2063 {
2024 LandAccessEntry entry = new LandAccessEntry(); 2064 LandAccessEntry entry = new LandAccessEntry();
@@ -2171,37 +2211,50 @@ namespace OpenSim.Region.CoreModules.World.Land
2171 2211
2172 private void AppendParcelsSummaryReport(StringBuilder report) 2212 private void AppendParcelsSummaryReport(StringBuilder report)
2173 { 2213 {
2174 report.AppendFormat("Land information for {0}\n", m_scene.Name); 2214 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName);
2175 2215 report.AppendFormat(
2176 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 2216 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
2177 cdt.AddColumn("Parcel Name", ConsoleDisplayUtil.ParcelNameSize); 2217 "Parcel Name",
2178 cdt.AddColumn("ID", 3); 2218 "Local ID",
2179 cdt.AddColumn("Area", 6); 2219 "Area",
2180 cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize); 2220 "AABBMin",
2181 cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize); 2221 "AABBMax",
2182 cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize); 2222 "Owner");
2183 2223
2184 lock (m_landList) 2224 lock (m_landList)
2185 { 2225 {
2186 foreach (ILandObject lo in m_landList.Values) 2226 foreach (ILandObject lo in m_landList.Values)
2187 { 2227 {
2188 LandData ld = lo.LandData; 2228 LandData ld = lo.LandData;
2189 string ownerName; 2229
2190 if (ld.IsGroupOwned) 2230 report.AppendFormat(
2191 { 2231 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
2192 GroupRecord rec = m_groupManager.GetGroupRecord(ld.GroupID); 2232 ld.Name, ld.LocalID, ld.Area, ld.AABBMin, ld.AABBMax, m_userManager.GetUserName(ld.OwnerID));
2193 ownerName = (rec != null) ? rec.GroupName : "Unknown Group";
2194 }
2195 else
2196 {
2197 ownerName = m_userManager.GetUserName(ld.OwnerID);
2198 }
2199 cdt.AddRow(
2200 ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, ownerName);
2201 } 2233 }
2202 } 2234 }
2235
2236 }
2237
2238 public void EnforceBans(ILandObject land, ScenePresence avatar)
2239 {
2240 if (avatar.AbsolutePosition.Z > LandChannel.BAN_LINE_SAFETY_HIEGHT)
2241 return;
2203 2242
2204 report.Append(cdt.ToString()); 2243 if (land.IsEitherBannedOrRestricted(avatar.UUID))
2244 {
2245 if (land.ContainsPoint(Convert.ToInt32(avatar.lastKnownAllowedPosition.X), Convert.ToInt32(avatar.lastKnownAllowedPosition.Y)))
2246 {
2247 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
2248 if (pos == null)
2249 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
2250 else
2251 ForceAvatarToPosition(avatar, (Vector3)pos);
2252 }
2253 else
2254 {
2255 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
2256 }
2257 }
2205 } 2258 }
2206 2259
2207 private void AppendParcelReport(StringBuilder report, ILandObject lo) 2260 private void AppendParcelReport(StringBuilder report, ILandObject lo)
@@ -2214,8 +2267,6 @@ namespace OpenSim.Region.CoreModules.World.Land
2214 cdl.AddRow("Description", ld.Description); 2267 cdl.AddRow("Description", ld.Description);
2215 cdl.AddRow("Snapshot ID", ld.SnapshotID); 2268 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2216 cdl.AddRow("Area", ld.Area); 2269 cdl.AddRow("Area", ld.Area);
2217 cdl.AddRow("Starts", lo.StartPoint);
2218 cdl.AddRow("Ends", lo.EndPoint);
2219 cdl.AddRow("AABB Min", ld.AABBMin); 2270 cdl.AddRow("AABB Min", ld.AABBMin);
2220 cdl.AddRow("AABB Max", ld.AABBMax); 2271 cdl.AddRow("AABB Max", ld.AABBMax);
2221 string ownerName; 2272 string ownerName;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index a0c1b9d..040c90b 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -50,7 +50,8 @@ namespace OpenSim.Region.CoreModules.World.Land
50 private readonly int landUnit = 4; 50 private readonly int landUnit = 4;
51 51
52 private int m_lastSeqId = 0; 52 private int m_lastSeqId = 0;
53 53 private int m_expiryCounter = 0;
54
54 protected Scene m_scene; 55 protected Scene m_scene;
55 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
56 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
@@ -58,7 +59,12 @@ namespace OpenSim.Region.CoreModules.World.Land
58 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>(); 59 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
59 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds 60 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
60 61
61 public bool[,] LandBitmap { get; set; } 62 private bool[,] m_landBitmap;
63 public bool[,] LandBitmap
64 {
65 get { return m_landBitmap; }
66 set { m_landBitmap = value; }
67 }
62 68
63 #endregion 69 #endregion
64 70
@@ -69,7 +75,13 @@ namespace OpenSim.Region.CoreModules.World.Land
69 return free; 75 return free;
70 } 76 }
71 77
72 public LandData LandData { get; set; } 78 protected LandData m_landData;
79 public LandData LandData
80 {
81 get { return m_landData; }
82
83 set { m_landData = value; }
84 }
73 85
74 public IPrimCounts PrimCounts { get; set; } 86 public IPrimCounts PrimCounts { get; set; }
75 87
@@ -141,6 +153,8 @@ namespace OpenSim.Region.CoreModules.World.Land
141 else 153 else
142 LandData.GroupID = UUID.Zero; 154 LandData.GroupID = UUID.Zero;
143 LandData.IsGroupOwned = is_group_owned; 155 LandData.IsGroupOwned = is_group_owned;
156
157 m_scene.EventManager.OnFrame += OnFrame;
144 } 158 }
145 159
146 #endregion 160 #endregion
@@ -195,10 +209,27 @@ namespace OpenSim.Region.CoreModules.World.Land
195 else 209 else
196 { 210 {
197 // Normal Calculations 211 // Normal Calculations
198 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 212 int parcelMax = (int)( (long)LandData.Area
199 * (float)m_scene.RegionInfo.ObjectCapacity 213 * (long)m_scene.RegionInfo.ObjectCapacity
200 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 214 * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
201 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 215 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
216 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
217 return parcelMax;
218 }
219 }
220
221 private int GetParcelBasePrimCount()
222 {
223 if (overrideParcelMaxPrimCount != null)
224 {
225 return overrideParcelMaxPrimCount(this);
226 }
227 else
228 {
229 // Normal Calculations
230 int parcelMax = (int)((long)LandData.Area
231 * (long)m_scene.RegionInfo.ObjectCapacity
232 / 65536L);
202 return parcelMax; 233 return parcelMax;
203 } 234 }
204 } 235 }
@@ -212,8 +243,10 @@ namespace OpenSim.Region.CoreModules.World.Land
212 else 243 else
213 { 244 {
214 //Normal Calculations 245 //Normal Calculations
215 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 246 int simMax = (int)( (long)LandData.SimwideArea
216 * (float)m_scene.RegionInfo.ObjectCapacity); 247 * (long)m_scene.RegionInfo.ObjectCapacity
248 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
249 // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
217 return simMax; 250 return simMax;
218 } 251 }
219 } 252 }
@@ -224,6 +257,9 @@ namespace OpenSim.Region.CoreModules.World.Land
224 257
225 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 258 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
226 { 259 {
260 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
261 return;
262
227 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 263 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
228 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 264 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
229 uint regionFlags = (uint)(RegionFlags.PublicAllowed 265 uint regionFlags = (uint)(RegionFlags.PublicAllowed
@@ -248,14 +284,15 @@ namespace OpenSim.Region.CoreModules.World.Land
248 remote_client.SendLandProperties(seq_id, 284 remote_client.SendLandProperties(seq_id,
249 snap_selection, request_result, this, 285 snap_selection, request_result, this,
250 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, 286 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
251 GetParcelMaxPrimCount(), 287 GetParcelBasePrimCount(),
252 GetSimulatorMaxPrimCount(), regionFlags); 288 GetSimulatorMaxPrimCount(), regionFlags);
253 } 289 }
254 290
255 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 291 public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
256 { 292 {
257 //Needs later group support 293 //Needs later group support
258 bool snap_selection = false; 294 snap_selection = false;
295 needOverlay = false;
259 LandData newData = LandData.Copy(); 296 LandData newData = LandData.Copy();
260 297
261 uint allowedDelta = 0; 298 uint allowedDelta = 0;
@@ -264,7 +301,7 @@ namespace OpenSim.Region.CoreModules.World.Land
264 // ParcelFlags.ForSaleObjects 301 // ParcelFlags.ForSaleObjects
265 // ParcelFlags.LindenHome 302 // ParcelFlags.LindenHome
266 303
267 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 304 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, false))
268 { 305 {
269 allowedDelta |= (uint)(ParcelFlags.AllowLandmark | 306 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
270 ParcelFlags.AllowTerraform | 307 ParcelFlags.AllowTerraform |
@@ -277,9 +314,12 @@ namespace OpenSim.Region.CoreModules.World.Land
277 ParcelFlags.AllowAPrimitiveEntry | 314 ParcelFlags.AllowAPrimitiveEntry |
278 ParcelFlags.AllowGroupObjectEntry | 315 ParcelFlags.AllowGroupObjectEntry |
279 ParcelFlags.AllowFly); 316 ParcelFlags.AllowFly);
317 newData.SeeAVs = args.SeeAVs;
318 newData.AnyAVSounds = args.AnyAVSounds;
319 newData.GroupAVSounds = args.GroupAVSounds;
280 } 320 }
281 321
282 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale)) 322 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
283 { 323 {
284 if (args.AuthBuyerID != newData.AuthBuyerID || 324 if (args.AuthBuyerID != newData.AuthBuyerID ||
285 args.SalePrice != newData.SalePrice) 325 args.SalePrice != newData.SalePrice)
@@ -302,30 +342,30 @@ namespace OpenSim.Region.CoreModules.World.Land
302 allowedDelta |= (uint)ParcelFlags.ForSale; 342 allowedDelta |= (uint)ParcelFlags.ForSale;
303 } 343 }
304 344
305 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces)) 345 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces, false))
306 { 346 {
307 newData.Category = args.Category; 347 newData.Category = args.Category;
308 348
309 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 349 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
310 ParcelFlags.AllowPublish | 350 ParcelFlags.AllowPublish |
311 ParcelFlags.MaturePublish); 351 ParcelFlags.MaturePublish) | (uint)(1 << 23);
312 } 352 }
313 353
314 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 354 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity, false))
315 { 355 {
316 newData.Description = args.Desc; 356 newData.Description = args.Desc;
317 newData.Name = args.Name; 357 newData.Name = args.Name;
318 newData.SnapshotID = args.SnapshotID; 358 newData.SnapshotID = args.SnapshotID;
319 } 359 }
320 360
321 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint)) 361 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint, false))
322 { 362 {
323 newData.LandingType = args.LandingType; 363 newData.LandingType = args.LandingType;
324 newData.UserLocation = args.UserLocation; 364 newData.UserLocation = args.UserLocation;
325 newData.UserLookAt = args.UserLookAt; 365 newData.UserLookAt = args.UserLookAt;
326 } 366 }
327 367
328 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia)) 368 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia, false))
329 { 369 {
330 newData.MediaAutoScale = args.MediaAutoScale; 370 newData.MediaAutoScale = args.MediaAutoScale;
331 newData.MediaID = args.MediaID; 371 newData.MediaID = args.MediaID;
@@ -346,7 +386,7 @@ namespace OpenSim.Region.CoreModules.World.Land
346 ParcelFlags.UseEstateVoiceChan); 386 ParcelFlags.UseEstateVoiceChan);
347 } 387 }
348 388
349 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses)) 389 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
350 { 390 {
351 newData.PassHours = args.PassHours; 391 newData.PassHours = args.PassHours;
352 newData.PassPrice = args.PassPrice; 392 newData.PassPrice = args.PassPrice;
@@ -354,13 +394,13 @@ namespace OpenSim.Region.CoreModules.World.Land
354 allowedDelta |= (uint)ParcelFlags.UsePassList; 394 allowedDelta |= (uint)ParcelFlags.UsePassList;
355 } 395 }
356 396
357 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed)) 397 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed, false))
358 { 398 {
359 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup | 399 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
360 ParcelFlags.UseAccessList); 400 ParcelFlags.UseAccessList);
361 } 401 }
362 402
363 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned)) 403 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned, false))
364 { 404 {
365 allowedDelta |= (uint)(ParcelFlags.UseBanList | 405 allowedDelta |= (uint)(ParcelFlags.UseBanList |
366 ParcelFlags.DenyAnonymous | 406 ParcelFlags.DenyAnonymous |
@@ -372,9 +412,16 @@ namespace OpenSim.Region.CoreModules.World.Land
372 uint preserve = LandData.Flags & ~allowedDelta; 412 uint preserve = LandData.Flags & ~allowedDelta;
373 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 413 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
374 414
415 uint curdelta = LandData.Flags ^ newData.Flags;
416 curdelta &= (uint)(ParcelFlags.SoundLocal);
417
418 if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
419 needOverlay = true;
420
375 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 421 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
376 SendLandUpdateToAvatarsOverMe(snap_selection); 422 return true;
377 } 423 }
424 return false;
378 } 425 }
379 426
380 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 427 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -395,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Land
395 UUID previousOwner = LandData.OwnerID; 442 UUID previousOwner = LandData.OwnerID;
396 443
397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 444 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
398 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 445// m_scene.EventManager.TriggerParcelPrimCountUpdate();
399 SendLandUpdateToAvatarsOverMe(true); 446 SendLandUpdateToAvatarsOverMe(true);
400 447
401 if (sellObjects) SellLandObjects(previousOwner); 448 if (sellObjects) SellLandObjects(previousOwner);
@@ -568,6 +615,7 @@ namespace OpenSim.Region.CoreModules.World.Land
568 615
569 public void SendLandUpdateToAvatarsOverMe(bool snap_selection) 616 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
570 { 617 {
618 m_scene.EventManager.TriggerParcelPrimCountUpdate();
571 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 619 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
572 { 620 {
573 ILandObject over = null; 621 ILandObject over = null;
@@ -594,6 +642,7 @@ namespace OpenSim.Region.CoreModules.World.Land
594 avatar.Invulnerable = true; 642 avatar.Invulnerable = true;
595 643
596 SendLandUpdateToClient(snap_selection, avatar.ControllingClient); 644 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
645 avatar.currentParcelUUID = LandData.GlobalID;
597 } 646 }
598 } 647 }
599 }); 648 });
@@ -722,10 +771,11 @@ namespace OpenSim.Region.CoreModules.World.Land
722 /// </summary> 771 /// </summary>
723 private void UpdateAABBAndAreaValues() 772 private void UpdateAABBAndAreaValues()
724 { 773 {
725 int min_x = 10000; 774
726 int min_y = 10000; 775 int min_x = Int32.MaxValue;
727 int max_x = 0; 776 int min_y = Int32.MaxValue;
728 int max_y = 0; 777 int max_x = Int32.MinValue;
778 int max_y = Int32.MinValue;
729 int tempArea = 0; 779 int tempArea = 0;
730 int x, y; 780 int x, y;
731 for (x = 0; x < LandBitmap.GetLength(0); x++) 781 for (x = 0; x < LandBitmap.GetLength(0); x++)
@@ -734,10 +784,14 @@ namespace OpenSim.Region.CoreModules.World.Land
734 { 784 {
735 if (LandBitmap[x, y] == true) 785 if (LandBitmap[x, y] == true)
736 { 786 {
737 if (min_x > x) min_x = x; 787 if (min_x > x)
738 if (min_y > y) min_y = y; 788 min_x = x;
739 if (max_x < x) max_x = x; 789 if (min_y > y)
740 if (max_y < y) max_y = y; 790 min_y = y;
791 if (max_x < x)
792 max_x = x;
793 if (max_y < y)
794 max_y = y;
741 tempArea += landUnit * landUnit; //16sqm peice of land 795 tempArea += landUnit * landUnit; //16sqm peice of land
742 } 796 }
743 } 797 }
@@ -745,24 +799,42 @@ namespace OpenSim.Region.CoreModules.World.Land
745 int tx = min_x * landUnit; 799 int tx = min_x * landUnit;
746 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 800 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
747 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 801 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
802 int htx;
803 if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
804 htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
805 else
806 htx = tx;
807
748 int ty = min_y * landUnit; 808 int ty = min_y * landUnit;
749 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 809 int hty;
750 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 810
811 if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
812 hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
813 else
814 hty = ty;
751 815
752 LandData.AABBMin = 816 LandData.AABBMin =
753 new Vector3( 817 new Vector3(
754 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 818 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
755 819
820 max_x++;
756 tx = max_x * landUnit; 821 tx = max_x * landUnit;
757 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 822 if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
758 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 823 htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
759 ty = max_y * landUnit; 824 else
760 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 825 htx = tx;
761 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 826
827 max_y++;
828 ty = max_y * 4;
829
830 if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
831 hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
832 else
833 hty = ty;
762 834
763 LandData.AABBMax 835 LandData.AABBMax
764 = new Vector3( 836 = new Vector3(
765 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 837 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
766 838
767 LandData.Area = tempArea; 839 LandData.Area = tempArea;
768 } 840 }
@@ -778,7 +850,6 @@ namespace OpenSim.Region.CoreModules.World.Land
778 public void SetLandBitmap(bool[,] bitmap) 850 public void SetLandBitmap(bool[,] bitmap)
779 { 851 {
780 LandBitmap = bitmap; 852 LandBitmap = bitmap;
781 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
782 ForceUpdateLandInfo(); 853 ForceUpdateLandInfo();
783 } 854 }
784 855
@@ -879,13 +950,32 @@ namespace OpenSim.Region.CoreModules.World.Land
879 private byte[] ConvertLandBitmapToBytes() 950 private byte[] ConvertLandBitmapToBytes()
880 { 951 {
881 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8]; 952 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
882 byte tempByte = 0; 953
883 int byteNum = 0; 954 int tempByte = 0;
884 int i = 0; 955 int i, byteNum = 0;
956 int mask = 1;
957 i = 0;
885 for (int y = 0; y < LandBitmap.GetLength(1); y++) 958 for (int y = 0; y < LandBitmap.GetLength(1); y++)
886 { 959 {
887 for (int x = 0; x < LandBitmap.GetLength(0); x++) 960 for (int x = 0; x < LandBitmap.GetLength(0); x++)
888 { 961 {
962 if (LandBitmap[x, y])
963 tempByte |= mask;
964 mask = mask << 1;
965 if (mask == 0x100)
966 {
967 mask = 1;
968 tempConvertArr[byteNum++] = (byte)tempByte;
969 tempByte = 0;
970 }
971 }
972 }
973
974 if(tempByte != 0 && byteNum < 512)
975 tempConvertArr[byteNum] = (byte)tempByte;
976
977
978/*
889 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 979 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
890 if (i % 8 == 0) 980 if (i % 8 == 0)
891 { 981 {
@@ -894,10 +984,13 @@ namespace OpenSim.Region.CoreModules.World.Land
894 i = 0; 984 i = 0;
895 byteNum++; 985 byteNum++;
896 } 986 }
987<<<<<<< HEAD
897 } 988 }
898 } 989 }
899 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>", 990 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>",
900 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 991 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
992=======
993 */
901 return tempConvertArr; 994 return tempConvertArr;
902 } 995 }
903 996
@@ -951,7 +1044,7 @@ namespace OpenSim.Region.CoreModules.World.Land
951 1044
952 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client) 1045 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
953 { 1046 {
954 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1047 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
955 { 1048 {
956 List<uint> resultLocalIDs = new List<uint>(); 1049 List<uint> resultLocalIDs = new List<uint>();
957 try 1050 try
@@ -1001,7 +1094,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1001 /// </param> 1094 /// </param>
1002 public void SendLandObjectOwners(IClientAPI remote_client) 1095 public void SendLandObjectOwners(IClientAPI remote_client)
1003 { 1096 {
1004 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1097 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
1005 { 1098 {
1006 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>(); 1099 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
1007 List<UUID> groups = new List<UUID>(); 1100 List<UUID> groups = new List<UUID>();
@@ -1233,6 +1326,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1233 public void SetMediaUrl(string url) 1326 public void SetMediaUrl(string url)
1234 { 1327 {
1235 LandData.MediaURL = url; 1328 LandData.MediaURL = url;
1329 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1236 SendLandUpdateToAvatarsOverMe(); 1330 SendLandUpdateToAvatarsOverMe();
1237 } 1331 }
1238 1332
@@ -1243,6 +1337,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1243 public void SetMusicUrl(string url) 1337 public void SetMusicUrl(string url)
1244 { 1338 {
1245 LandData.MusicURL = url; 1339 LandData.MusicURL = url;
1340 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1246 SendLandUpdateToAvatarsOverMe(); 1341 SendLandUpdateToAvatarsOverMe();
1247 } 1342 }
1248 1343
@@ -1257,6 +1352,17 @@ namespace OpenSim.Region.CoreModules.World.Land
1257 1352
1258 #endregion 1353 #endregion
1259 1354
1355 private void OnFrame()
1356 {
1357 m_expiryCounter++;
1358
1359 if (m_expiryCounter >= 50)
1360 {
1361 ExpireAccessList();
1362 m_expiryCounter = 0;
1363 }
1364 }
1365
1260 private void ExpireAccessList() 1366 private void ExpireAccessList()
1261 { 1367 {
1262 List<LandAccessEntry> delete = new List<LandAccessEntry>(); 1368 List<LandAccessEntry> delete = new List<LandAccessEntry>();
@@ -1267,7 +1373,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1267 delete.Add(entry); 1373 delete.Add(entry);
1268 } 1374 }
1269 foreach (LandAccessEntry entry in delete) 1375 foreach (LandAccessEntry entry in delete)
1376 {
1270 LandData.ParcelAccessList.Remove(entry); 1377 LandData.ParcelAccessList.Remove(entry);
1378 ScenePresence presence;
1379
1380 if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
1381 {
1382 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1383 if (land.LandData.LocalID == LandData.LocalID)
1384 {
1385 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1386 presence.TeleportWithMomentum(pos, null);
1387 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1388 }
1389 }
1390 m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1391 }
1271 1392
1272 if (delete.Count > 0) 1393 if (delete.Count > 0)
1273 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this); 1394 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/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 796a15f..5155804 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -112,7 +112,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
112 //} 112 //}
113 //t = System.Environment.TickCount - t; 113 //t = System.Environment.TickCount - t;
114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); 114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
115
116 if (drawPrimVolume) 115 if (drawPrimVolume)
117 { 116 {
118 DrawObjectVolume(m_scene, mapbmp); 117 DrawObjectVolume(m_scene, mapbmp);
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index 9f23141..0ec2053 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
288 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height) 288 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
289 { 289 {
290 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>", 290 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
291 LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height); 291 "[TEXTURED MAP TILE RENDERER]", mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
292 } 292 }
293 293
294 // These textures should be in the AssetCache anyway, as every client conneting to this 294 // These textures should be in the AssetCache anyway, as every client conneting to this
@@ -371,8 +371,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
371 // first, rescale h to 0.0 - 1.0 371 // first, rescale h to 0.0 - 1.0
372 hmod = (hmod - low) / (high - low); 372 hmod = (hmod - low) / (high - low);
373 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 373 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4
374 if (hmod < 1f/3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f); 374 if (hmod < 1f / 3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f);
375 else if (hmod < 2f/3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f); 375 else if (hmod < 2f / 3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f);
376 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f); 376 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f);
377 } 377 }
378 378
diff --git a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
index 0a4e83e..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,8 +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 {0}", presence.Name); 213 if (m_enableWindlight && m_scene.RegionInfo.WindlightSettings.valid)
211 214 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client");
212 SendProfileToClient(presence.ControllingClient); 215 SendProfileToClient(presence.ControllingClient);
213 } 216 }
214 217
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 2abc910..0e0f05f 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -173,6 +173,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
173 return false; 173 return false;
174 } 174 }
175 175
176 if ((perms & (uint)PermissionMask.Copy) == 0)
177 {
178 if (m_dialogModule != null)
179 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
180 return false;
181 }
182
176 AssetBase asset = m_scene.CreateAsset( 183 AssetBase asset = m_scene.CreateAsset(
177 group.GetPartName(localID), 184 group.GetPartName(localID),
178 group.GetPartDescription(localID), 185 group.GetPartDescription(localID),
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 780ec69..765c1f2 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -43,8 +43,8 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
43 43
44namespace OpenSim.Region.CoreModules.World.Permissions 44namespace OpenSim.Region.CoreModules.World.Permissions
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PermissionsModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultPermissionsModule")]
47 public class PermissionsModule : INonSharedRegionModule, IPermissionsModule 47 public class DefaultPermissionsModule : INonSharedRegionModule, IPermissionsModule
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
@@ -349,7 +349,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
349 349
350 public string Name 350 public string Name
351 { 351 {
352 get { return "PermissionsModule"; } 352 get { return "DefaultPermissionsModule"; }
353 } 353 }
354 354
355 public Type ReplaceableInterface 355 public Type ReplaceableInterface
@@ -705,7 +705,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
705 if (user == objectOwner) 705 if (user == objectOwner)
706 return PermissionClass.Owner; 706 return PermissionClass.Owner;
707 707
708 if (IsFriendWithPerms(user, objectOwner)) 708 if (IsFriendWithPerms(user, objectOwner) && !obj.ParentGroup.IsAttachment)
709 return PermissionClass.Owner; 709 return PermissionClass.Owner;
710 710
711 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set 711 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
@@ -1052,7 +1052,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1052 return GenericObjectPermission(editorID, objectID, false); 1052 return GenericObjectPermission(editorID, objectID, false);
1053 } 1053 }
1054 1054
1055 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene) 1055 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager)
1056 { 1056 {
1057 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1057 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1058 if (m_bypassPermissions) return m_bypassPermissionsValue; 1058 if (m_bypassPermissions) return m_bypassPermissionsValue;
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
index bb4dcce..b9bcb8b 100644
--- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -271,8 +271,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
271 float totalFrameTime = stats[8]; 271 float totalFrameTime = stats[8];
272// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator 272// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator
273 float physicsFrameTime = stats[10]; 273 float physicsFrameTime = stats[10];
274 float otherFrameTime = stats[11]; 274 float otherFrameTime = stats[12];
275// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored 275// float imageFrameTime = stats.StatsBlock[11].StatValue; // Ignored
276 float inPacketsPerSecond = stats[13]; 276 float inPacketsPerSecond = stats[13];
277 float outPacketsPerSecond = stats[14]; 277 float outPacketsPerSecond = stats[14];
278 float unackedBytes = stats[15]; 278 float unackedBytes = stats[15];
@@ -280,7 +280,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
280 float pendingDownloads = stats[17]; 280 float pendingDownloads = stats[17];
281 float pendingUploads = stats[18]; 281 float pendingUploads = stats[18];
282 float activeScripts = stats[19]; 282 float activeScripts = stats[19];
283 float scriptLinesPerSecond = stats[20]; 283 float scriptLinesPerSecond = stats[23];
284 284
285 StringBuilder sb = new StringBuilder(); 285 StringBuilder sb = new StringBuilder();
286 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName); 286 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 75a8295..e6a0205 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);
@@ -118,10 +131,14 @@ namespace OpenSim.Region.CoreModules.World.Region
118 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice) 131 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice)
119 { 132 {
120 if (m_CountdownTimer != null) 133 if (m_CountdownTimer != null)
121 return; 134 {
135 m_CountdownTimer.Stop();
136 m_CountdownTimer = null;
137 }
122 138
123 if (alerts == null) 139 if (alerts == null)
124 { 140 {
141 CreateMarkerFile();
125 m_Scene.RestartNow(); 142 m_Scene.RestartNow();
126 return; 143 return;
127 } 144 }
@@ -129,25 +146,28 @@ namespace OpenSim.Region.CoreModules.World.Region
129 m_Message = message; 146 m_Message = message;
130 m_Initiator = initiator; 147 m_Initiator = initiator;
131 m_Notice = notice; 148 m_Notice = notice;
149 m_CurrentAlerts = alerts;
132 m_Alerts = new List<int>(alerts); 150 m_Alerts = new List<int>(alerts);
133 m_Alerts.Sort(); 151 m_Alerts.Sort();
134 m_Alerts.Reverse(); 152 m_Alerts.Reverse();
135 153
136 if (m_Alerts[0] == 0) 154 if (m_Alerts[0] == 0)
137 { 155 {
156 CreateMarkerFile();
138 m_Scene.RestartNow(); 157 m_Scene.RestartNow();
139 return; 158 return;
140 } 159 }
141 160
142 int nextInterval = DoOneNotice(); 161 int nextInterval = DoOneNotice(true);
143 162
144 SetTimer(nextInterval); 163 SetTimer(nextInterval);
145 } 164 }
146 165
147 public int DoOneNotice() 166 public int DoOneNotice(bool sendOut)
148 { 167 {
149 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 168 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
150 { 169 {
170 CreateMarkerFile();
151 m_Scene.RestartNow(); 171 m_Scene.RestartNow();
152 return 0; 172 return 0;
153 } 173 }
@@ -168,34 +188,37 @@ namespace OpenSim.Region.CoreModules.World.Region
168 188
169 m_Alerts.RemoveAt(0); 189 m_Alerts.RemoveAt(0);
170 190
171 int minutes = currentAlert / 60; 191 if (sendOut)
172 string currentAlertString = String.Empty;
173 if (minutes > 0)
174 { 192 {
175 if (minutes == 1) 193 int minutes = currentAlert / 60;
176 currentAlertString += "1 minute"; 194 string currentAlertString = String.Empty;
177 else 195 if (minutes > 0)
178 currentAlertString += String.Format("{0} minutes", minutes); 196 {
197 if (minutes == 1)
198 currentAlertString += "1 minute";
199 else
200 currentAlertString += String.Format("{0} minutes", minutes);
201 if ((currentAlert % 60) != 0)
202 currentAlertString += " and ";
203 }
179 if ((currentAlert % 60) != 0) 204 if ((currentAlert % 60) != 0)
180 currentAlertString += " and "; 205 {
181 } 206 int seconds = currentAlert % 60;
182 if ((currentAlert % 60) != 0) 207 if (seconds == 1)
183 { 208 currentAlertString += "1 second";
184 int seconds = currentAlert % 60; 209 else
185 if (seconds == 1) 210 currentAlertString += String.Format("{0} seconds", seconds);
186 currentAlertString += "1 second"; 211 }
187 else
188 currentAlertString += String.Format("{0} seconds", seconds);
189 }
190 212
191 string msg = String.Format(m_Message, currentAlertString); 213 string msg = String.Format(m_Message, currentAlertString);
192 214
193 if (m_DialogModule != null && msg != String.Empty) 215 if (m_DialogModule != null && msg != String.Empty)
194 { 216 {
195 if (m_Notice) 217 if (m_Notice)
196 m_DialogModule.SendGeneralAlert(msg); 218 m_DialogModule.SendGeneralAlert(msg);
197 else 219 else
198 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg); 220 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg);
221 }
199 } 222 }
200 223
201 return currentAlert - nextAlert; 224 return currentAlert - nextAlert;
@@ -226,7 +249,27 @@ namespace OpenSim.Region.CoreModules.World.Region
226 249
227 private void OnTimer(object source, ElapsedEventArgs e) 250 private void OnTimer(object source, ElapsedEventArgs e)
228 { 251 {
229 SetTimer(DoOneNotice()); 252 int nextInterval = DoOneNotice(true);
253
254 SetTimer(nextInterval);
255 }
256
257 public void DelayRestart(int seconds, string message)
258 {
259 if (m_CountdownTimer == null)
260 return;
261
262 m_CountdownTimer.Stop();
263 m_CountdownTimer = null;
264
265 m_Alerts = new List<int>(m_CurrentAlerts);
266 m_Alerts.Add(seconds);
267 m_Alerts.Sort();
268 m_Alerts.Reverse();
269
270 int nextInterval = DoOneNotice(false);
271
272 SetTimer(nextInterval);
230 } 273 }
231 274
232 public void AbortRestart(string message) 275 public void AbortRestart(string message)
@@ -236,8 +279,12 @@ namespace OpenSim.Region.CoreModules.World.Region
236 m_CountdownTimer.Stop(); 279 m_CountdownTimer.Stop();
237 m_CountdownTimer = null; 280 m_CountdownTimer = null;
238 if (m_DialogModule != null && message != String.Empty) 281 if (m_DialogModule != null && message != String.Empty)
239 m_DialogModule.SendGeneralAlert(message); 282 m_DialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
283 //m_DialogModule.SendGeneralAlert(message);
240 } 284 }
285 if (m_MarkerPath != String.Empty)
286 File.Delete(Path.Combine(m_MarkerPath,
287 m_Scene.RegionInfo.RegionID.ToString()));
241 } 288 }
242 289
243 private void HandleRegionRestart(string module, string[] args) 290 private void HandleRegionRestart(string module, string[] args)
@@ -282,5 +329,25 @@ namespace OpenSim.Region.CoreModules.World.Region
282 329
283 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 330 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
284 } 331 }
332
333 protected void CreateMarkerFile()
334 {
335 if (m_MarkerPath == String.Empty)
336 return;
337
338 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
339 try
340 {
341 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
342 FileStream fs = File.Create(path);
343 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
344 Byte[] buf = enc.GetBytes(pidstring);
345 fs.Write(buf, 0, buf.Length);
346 fs.Close();
347 }
348 catch (Exception)
349 {
350 }
351 }
285 } 352 }
286} \ No newline at end of file 353}
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index d093224..9c99c19 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -48,6 +48,18 @@ namespace OpenSim.Region.CoreModules.World.Sound
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
51 public enum SoundFlags: byte
52 {
53 NONE = 0,
54 LOOP = 1 << 0,
55 SYNC_MASTER = 1<<1,
56 SYNC_SLAVE = 1<<2,
57 SYNC_PENDING = 1<<3,
58 QUEUE = 1<<4,
59 STOP = 1<<5,
60 SYNC_MASK = SYNC_MASTER | SYNC_SLAVE | SYNC_PENDING
61 }
62
51 public bool Enabled { get; private set; } 63 public bool Enabled { get; private set; }
52 64
53 public float MaxDistance { get; private set; } 65 public float MaxDistance { get; private set; }
@@ -124,26 +136,30 @@ namespace OpenSim.Region.CoreModules.World.Sound
124 if (radius == 0) 136 if (radius == 0)
125 radius = MaxDistance; 137 radius = MaxDistance;
126 138
127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 139 if (part.SoundQueueing)
140 flags |= (byte)SoundFlags.QUEUE;
141
142 if (grp.IsAttachment)
128 { 143 {
129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 144 ScenePresence ssp = null;
130 if (dis > MaxDistance) // Max audio distance 145 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
131 return; 146 return;
132 147
133 if (grp.IsAttachment) 148 if (!ssp.ParcelAllowThisAvatarSounds)
134 { 149 return;
135 if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID)
136 return;
137 150
138 if (sp.ControllingClient.AgentId == grp.OwnerID) 151 if (grp.HasPrivateAttachmentPoint)
139 dis = 0; 152 {
153 ssp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
154 ownerID, (float)gain, flags);
155 return;
140 } 156 }
157 }
141 158
142 // Scale by distance 159 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
143 double thisSpGain = gain * ((radius - dis) / radius); 160 {
144
145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, 161 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags); 162 ownerID, (float)gain, flags);
147 }); 163 });
148 } 164 }
149 165
@@ -151,20 +167,33 @@ namespace OpenSim.Region.CoreModules.World.Sound
151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 167 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
152 { 168 {
153 SceneObjectPart part; 169 SceneObjectPart part;
170 ScenePresence ssp = null;
154 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 171 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
155 { 172 {
156 ScenePresence sp; 173 if (!m_scene.TryGetScenePresence(ownerID, out ssp))
157 if (!m_scene.TryGetScenePresence(ownerID, out sp)) 174 return;
175 if (!ssp.ParcelAllowThisAvatarSounds)
158 return; 176 return;
159 } 177 }
160 else 178 else
161 { 179 {
162 SceneObjectGroup grp = part.ParentGroup; 180 SceneObjectGroup grp = part.ParentGroup;
163 181
164 if (grp.IsAttachment && grp.AttachmentPoint > 30) 182 if (grp.IsAttachment)
165 { 183 {
166 objectID = ownerID; 184 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
167 parentID = ownerID; 185 return;
186
187 if (!ssp.ParcelAllowThisAvatarSounds)
188 return;
189
190 if (grp.HasPrivateAttachmentPoint)
191 {
192 ssp.ControllingClient.SendTriggeredSound(soundId, ownerID,
193 objectID, parentID, handle, position,
194 (float)gain);
195 return;
196 }
168 } 197 }
169 } 198 }
170 199
@@ -174,16 +203,12 @@ namespace OpenSim.Region.CoreModules.World.Sound
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 203 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 204 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 205 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 206 if (dis > radius) // Max audio distance
178 if (dis > MaxDistance) // Max audio distance
179 return; 207 return;
180 208
181 // Scale by distance
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID, 209 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position, 210 objectID, parentID, handle, position,
186 (float)thisSpGain); 211 (float)gain);
187 }); 212 });
188 } 213 }
189 214
@@ -198,40 +223,13 @@ namespace OpenSim.Region.CoreModules.World.Sound
198 223
199 private static void StopSound(SceneObjectPart m_host) 224 private static void StopSound(SceneObjectPart m_host)
200 { 225 {
201 m_host.AdjustSoundGain(0); 226// m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead 227 m_host.Sound = UUID.Zero;
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 228 m_host.SoundFlags = (byte)SoundFlags.STOP;
204 { 229 m_host.SoundRadius = 0;
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 230 m_host.SoundGain = 0;
206 { 231 m_host.ScheduleFullUpdate();
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) 232 m_host.SendFullUpdateToAllClients();
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 } 233 }
236 234
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) 235 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
@@ -248,7 +246,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
248 246
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 247 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 { 248 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) 249 if (Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) < radius)
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); 250 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 }); 251 });
254 } 252 }
@@ -262,21 +260,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
262 // 20080530 Updated to remove code duplication 260 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work 261 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID, 262 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster) 263 double volume, double radius, bool isMaster, bool isSlave)
266 { 264 {
267 SceneObjectPart m_host; 265 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) 266 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return; 267 return;
270 268
269 byte iflags = 1; // looping
271 if (isMaster) 270 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 271 iflags |= (byte)SoundFlags.SYNC_MASTER;
273 272 // TODO check viewer seems to accept both
274 if (m_host.Sound != UUID.Zero) 273 if (isSlave)
275 StopSound(m_host); 274 iflags |= (byte)SoundFlags.SYNC_SLAVE;
275 if (m_host.SoundQueueing)
276 iflags |= (byte)SoundFlags.QUEUE;
276 277
277 m_host.Sound = soundID; 278 m_host.Sound = soundID;
278 m_host.SoundGain = volume; 279 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping 280 m_host.SoundFlags = iflags;
280 m_host.SoundRadius = radius; 281 m_host.SoundRadius = radius;
281 282
282 m_host.ScheduleFullUpdate(); 283 m_host.ScheduleFullUpdate();
@@ -301,42 +302,19 @@ namespace OpenSim.Region.CoreModules.World.Sound
301 Vector3 position = part.AbsolutePosition; // region local 302 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle; 303 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303 304
304 if (useMaster) 305 if(triggered)
305 { 306 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else 307 else
334 { 308 {
335 if (triggered) 309 byte bflags = 0;
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); 310
337 else 311 if (isMaster)
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); 312 bflags |= (byte)SoundFlags.SYNC_MASTER;
339 } 313 // TODO check viewer seems to accept both
314 if (useMaster)
315 bflags |= (byte)SoundFlags.SYNC_SLAVE;
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, bflags, radius);
317 }
340 } 318 }
341 319
342 public void TriggerSoundLimited(UUID objectID, UUID sound, 320 public void TriggerSoundLimited(UUID objectID, UUID sound,
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
index 36917e9..b456aa1 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
64 64
65 for (int i = 0; i < rounds; i++) 65 for (int i = 0; i < rounds; i++)
66 { 66 {
67 smoothFunction.FloodEffect(map, bitmap, 1.0); 67 smoothFunction.FloodEffect(map, bitmap, 1.0, 0, map.Width - 1, 0, map.Height - 1);
68 } 68 }
69 } 69 }
70 70
@@ -99,7 +99,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
99 } 99 }
100 } 100 }
101 101
102 raiseFunction.FloodEffect(map, bitmap, height); 102 raiseFunction.FloodEffect(map, bitmap, height, 0, map.Width - 1, 0, map.Height - 1);
103 } 103 }
104 } 104 }
105 } 105 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
index dc76ad5..3222524 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
84 for (y = 0; y < map.Height; y++) 84 for (y = 0; y < map.Height; y++)
85 { 85 {
86 if (cliffMask[x, y]) 86 if (cliffMask[x, y])
87 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1); 87 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1,0,map.Width - 1,0,map.Height - 1);
88 } 88 }
89 } 89 }
90 90
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
index 89087b1..80396c4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
@@ -53,4 +53,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
53 53
54 #endregion 54 #endregion
55 } 55 }
56} \ No newline at end of file 56}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d5c77ec..e8c719a 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
128 colours.Save(stream, ImageFormat.Png); 128 colours.Save(stream, ImageFormat.Png);
129 } 129 }
130 130
131 public virtual void SaveFile(ITerrainChannel m_channel, string filename, 131 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
132 int offsetX, int offsetY, 132 int offsetX, int offsetY,
133 int fileWidth, int fileHeight, 133 int fileWidth, int fileHeight,
134 int regionSizeX, int regionSizeY) 134 int regionSizeX, int regionSizeY)
@@ -162,13 +162,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
162 { 162 {
163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); 163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
164 } 164 }
165 165
166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel); 166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel);
167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY); 167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY);
168 for (int x = 0; x < regionSizeX; x++) 168 for (int x = 0; x < regionSizeX; x++)
169 for (int y = 0; y < regionSizeY; y++) 169 for (int y = 0; y < regionSizeY; y++)
170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y)); 170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
171 171
172 Save(newBitmap, filename); 172 Save(newBitmap, filename);
173 } 173 }
174 finally 174 finally
@@ -213,8 +213,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
213 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns> 213 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns>
214 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) 214 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map)
215 { 215 {
216 // Bitmap bmp = new Bitmap(map.Width, map.Height, PixelFormat.Format24bppRgb);
216 Bitmap bmp = new Bitmap(map.Width, map.Height); 217 Bitmap bmp = new Bitmap(map.Width, map.Height);
217 218
219
218 const int pallete = 256; 220 const int pallete = 256;
219 221
220 Color[] grays = new Color[pallete]; 222 Color[] grays = new Color[pallete];
@@ -227,59 +229,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
227 { 229 {
228 for (int x = 0; x < map.Width; x++) 230 for (int x = 0; x < map.Width; x++)
229 { 231 {
230 // 512 is the largest possible height before colours clamp 232 // to change this, loading also needs change
231 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 128.0), 0.0) * (pallete - 1));
232
233 // Handle error conditions
234 if (colorindex > pallete - 1 || colorindex < 0)
235 bmp.SetPixel(x, map.Height - y - 1, Color.Red);
236 else
237 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
238 }
239 }
240 return bmp;
241 }
242
243 /// <summary>
244 /// Protected method, generates a coloured bitmap
245 /// image from a specified terrain channel.
246 /// </summary>
247 /// <param name="map">The terrain channel to export to bitmap</param>
248 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns>
249 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map)
250 {
251 int pallete;
252 Bitmap bmp;
253 Color[] colours;
254 233
255 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png")) 234 // int colorindex = (int)map[x, y]; // one to one conversion 0 - 255m range
256 { 235 // int colorindex = (int)map[x, y] / 2; // 0 - 510 range
257 pallete = gradientmapLd.Height;
258
259 bmp = new Bitmap(map.Width, map.Height);
260 colours = new Color[pallete];
261
262 for (int i = 0; i < pallete; i++)
263 {
264 colours[i] = gradientmapLd.GetPixel(0, i);
265 }
266 }
267 236
268 for (int y = 0; y < map.Height; y++) 237 int colorindex = (int)map[x, y] * 2; // the original 0 - 127.5 range
269 {
270 for (int x = 0; x < map.Width; x++)
271 {
272 // 512 is the largest possible height before colours clamp
273 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1));
274 238
275 // Handle error conditions 239 // clamp it not adding the red warning
276 if (colorindex > pallete - 1 || colorindex < 0) 240 if (colorindex < 0)
277 bmp.SetPixel(x, map.Height - y - 1, Color.Red); 241 colorindex = 0;
278 else 242 else if (colorindex >= pallete)
279 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); 243 colorindex = pallete - 1;
244 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
280 } 245 }
281 } 246 }
282 return bmp; 247 return bmp;
283 } 248 }
284 } 249 }
285} 250}
251
252
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
index be1fb24..59994e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
@@ -57,6 +57,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
57 57
58 public LLRAW() 58 public LLRAW()
59 { 59 {
60 }
61
62 private void BuildLookupHeightTable()
63 {
60 LookupHeightTable = new HeightmapLookupValue[256 * 256]; 64 LookupHeightTable = new HeightmapLookupValue[256 * 256];
61 65
62 for (int i = 0; i < 256; i++) 66 for (int i = 0; i < 256; i++)
@@ -186,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
186 190
187 public void SaveStream(Stream s, ITerrainChannel map) 191 public void SaveStream(Stream s, ITerrainChannel map)
188 { 192 {
193 if (LookupHeightTable == null)
194 BuildLookupHeightTable();
195
189 using (BinaryWriter binStream = new BinaryWriter(s)) 196 using (BinaryWriter binStream = new BinaryWriter(s))
190 { 197 {
191 // Output the calculated raw 198 // Output the calculated raw
@@ -241,6 +248,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
241 } 248 }
242 } 249 }
243 } 250 }
251 LookupHeightTable = null;
244 } 252 }
245 253
246 public string FileExtension 254 public string FileExtension
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
index 774e7b2..0c4171e 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
@@ -33,15 +33,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 double sum = 0.0; 39 double sum = 0.0;
39 double steps = 0.0; 40 double steps = 0.0;
40 41
41 int x, y; 42 int x, y;
42 for (x = 0; x < map.Width; x++) 43 for (x = startX; x <= endX; x++)
43 { 44 {
44 for (y = 0; y < map.Height; y++) 45 for (y = startY; y <= endY; y++)
45 { 46 {
46 if (fillArea[x, y]) 47 if (fillArea[x, y])
47 { 48 {
@@ -55,9 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 56
56 double str = 0.1 * strength; // == 0.2 in the default client 57 double str = 0.1 * strength; // == 0.2 in the default client
57 58
58 for (x = 0; x < map.Width; x++) 59 for (x = startX; x <= endX; x++)
59 { 60 {
60 for (y = 0; y < map.Height; y++) 61 for (y = startY; y <= endY; y++)
61 { 62 {
62 if (fillArea[x, y]) 63 if (fillArea[x, y])
63 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str); 64 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
index 3e87390..a275a86 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
@@ -33,13 +33,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 int x; 39 int x,y;
39 for (x = 0; x < map.Width; x++) 40 for (x = startX; x <= endX; x++)
40 { 41 {
41 int y; 42 for (y = startY; y <= endY; y++)
42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 if (fillArea[x, y]) 44 if (fillArea[x, y])
45 { 45 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
index b6c635c..d634e8b 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
@@ -35,18 +35,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
35 { 35 {
36 #region ITerrainFloodEffect Members 36 #region ITerrainFloodEffect Members
37 37
38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
39 int startX, int endX, int startY, int endY)
39 { 40 {
40 int x; 41 int x, y;
41 for (x = 0; x < map.Width; x++) 42 for (x = startX; x <= endX; x++)
42 { 43 {
43 int y; 44 for (y = startY; y <= endY; y++)
44 for (y = 0; y < map.Height; y++)
45 { 45 {
46 if (fillArea[x, y]) 46 if (fillArea[x, y])
47 { 47 {
48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0); 48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
49
50 map[x, y] += noise * strength; 49 map[x, y] += noise * strength;
51 } 50 }
52 } 51 }
@@ -55,4 +54,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 54
56 #endregion 55 #endregion
57 } 56 }
58} \ No newline at end of file 57}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
index 3bdc5e7..6ccd5df 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
@@ -33,13 +33,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 int x; 39 int x,y;
39 for (x = 0; x < map.Width; x++) 40 for (x = startX; x <= endX; x++)
40 { 41 {
41 int y; 42 for (y = startY; y <= endY; y++)
42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 if (fillArea[x, y]) 44 if (fillArea[x, y])
45 { 45 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
index c5527fa..4230133 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
@@ -46,13 +46,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
46 /// <param name="map">the current heightmap</param> 46 /// <param name="map">the current heightmap</param>
47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param> 47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param>
48 /// <param name="strength">unused</param> 48 /// <param name="strength">unused</param>
49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
50 int startX, int endX, int startY, int endY)
50 { 51 {
51 int x; 52 int x, y;
52 for (x = 0; x < map.Width; x++) 53 for (x = startX; x <= endX; x++)
53 { 54 {
54 int y; 55 for (y = startY; y <= endY; y++)
55 for (y = 0; y < map.Height; y++)
56 { 56 {
57 if (fillArea[x, y]) 57 if (fillArea[x, y])
58 { 58 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
index 6b07747..6c0d60d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
@@ -33,16 +33,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 double area = strength; 39 double area = strength;
39 double step = strength / 4.0; 40 double step = strength / 4.0;
40 41
41 double[,] manipulate = new double[map.Width,map.Height]; 42 double[,] manipulate = new double[map.Width,map.Height];
42 int x, y; 43 int x, y;
43 for (x = 0; x < map.Width; x++) 44 for (x = startX; x <= endX; x++)
44 { 45 {
45 for (y = 0; y < map.Height; y++) 46 for (y = startY; y <= endY; y++)
46 { 47 {
47 if (!fillArea[x, y]) 48 if (!fillArea[x, y])
48 continue; 49 continue;
@@ -64,9 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
64 manipulate[x, y] = average / avgsteps; 65 manipulate[x, y] = average / avgsteps;
65 } 66 }
66 } 67 }
67 for (x = 0; x < map.Width; x++) 68 for (x = startX; x <= endX; x++)
68 { 69 {
69 for (y = 0; y < map.Height; y++) 70 for (y = startY; y <= endY; y++)
70 { 71 {
71 if (!fillArea[x, y]) 72 if (!fillArea[x, y])
72 continue; 73 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
index 3984a30..6324aca 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
@@ -32,6 +32,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
32{ 32{
33 public interface ITerrainFloodEffect 33 public interface ITerrainFloodEffect
34 { 34 {
35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength); 35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength,
36 int startX, int endX, int startY, int endY);
36 } 37 }
37} \ No newline at end of file 38} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
index b73defd..d0b05e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
@@ -31,6 +31,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
31{ 31{
32 public interface ITerrainPaintableEffect 32 public interface ITerrainPaintableEffect
33 { 33 {
34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z, double strength, double duration); 34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z,
35 double strength, double duration, int startX, int endX, int startY, int endY);
35 } 36 }
36} 37}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
index 7a78cd8..7358ba3 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
@@ -151,7 +151,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
151 151
152 #region ITerrainPaintableEffect Members 152 #region ITerrainPaintableEffect Members
153 153
154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
155 double strength, double duration, int startX, int endX, int startY, int endY)
155 { 156 {
156 strength = TerrainUtil.MetersToSphericalStrength(strength); 157 strength = TerrainUtil.MetersToSphericalStrength(strength);
157 158
@@ -163,18 +164,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
163 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); 164 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);
164 165
165 // Fill with rain 166 // Fill with rain
166 for (x = 0; x < water.Width; x++) 167 for (x = startX; x <= endX; x++)
167 for (y = 0; y < water.Height; y++) 168 {
168 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); 169 for (y = startY; y <= endY; y++)
170 {
171 if (mask[x, y])
172 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
173 }
174 }
169 175
170 for (int i = 0; i < rounds; i++) 176 for (int i = 0; i < rounds; i++)
171 { 177 {
172 // Erode underlying terrain 178 // Erode underlying terrain
173 for (x = 0; x < water.Width; x++) 179 for (x = startX; x <= endX; x++)
174 { 180 {
175 for (y = 0; y < water.Height; y++) 181 for (y = startY; y <= endY; y++)
176 { 182 {
177 if (mask[x,y]) 183 if (mask[x, y])
178 { 184 {
179 const double solConst = (1.0 / rounds); 185 const double solConst = (1.0 / rounds);
180 double sedDelta = water[x, y] * solConst; 186 double sedDelta = water[x, y] * solConst;
@@ -185,9 +191,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
185 } 191 }
186 192
187 // Move water 193 // Move water
188 for (x = 0; x < water.Width; x++) 194 for (x = startX; x <= endX; x++)
189 { 195 {
190 for (y = 0; y < water.Height; y++) 196 for (y = startY; y <= endY; y++)
191 { 197 {
192 if (water[x, y] <= 0) 198 if (water[x, y] <= 0)
193 continue; 199 continue;
@@ -296,7 +302,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
296 double sedimentDeposit = sediment[x, y] - waterCapacity; 302 double sedimentDeposit = sediment[x, y] - waterCapacity;
297 if (sedimentDeposit > 0) 303 if (sedimentDeposit > 0)
298 { 304 {
299 if (mask[x,y]) 305 if (mask[x, y])
300 { 306 {
301 sediment[x, y] -= sedimentDeposit; 307 sediment[x, y] -= sedimentDeposit;
302 map[x, y] += sedimentDeposit; 308 map[x, y] += sedimentDeposit;
@@ -309,10 +315,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
309 // Deposit any remainder (should be minimal) 315 // Deposit any remainder (should be minimal)
310 for (x = 0; x < water.Width; x++) 316 for (x = 0; x < water.Width; x++)
311 for (y = 0; y < water.Height; y++) 317 for (y = 0; y < water.Height; y++)
312 if (mask[x,y] && sediment[x, y] > 0) 318 if (mask[x, y] && sediment[x, y] > 0)
313 map[x, y] += sediment[x, y]; 319 map[x, y] += sediment[x, y];
314 } 320 }
315
316 #endregion 321 #endregion
317 } 322 }
318} 323}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
index 9aa3dff..8937f63 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
@@ -35,16 +35,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 { 35 {
36 #region ITerrainPaintableEffect Members 36 #region ITerrainPaintableEffect Members
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength); 41 strength = TerrainUtil.MetersToSphericalStrength(strength);
41 42
42 int x, y; 43 int x, y;
43 44
44 // blend in map 45 // blend in map
45 for (x = 0; x < map.Width; x++) 46 for (x = startX; x <= endX; x++)
46 { 47 {
47 for (y = 0; y < map.Height; y++) 48 for (y = startY; y <= endY; y++)
48 { 49 {
49 if (!mask[x,y]) 50 if (!mask[x,y])
50 continue; 51 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
index 68145f2..bbf9407 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
@@ -34,34 +34,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
38 double strength, double duration, int startX, int endX, int startY, int endY)
38 { 39 {
39 int s = (int) (Math.Pow(2, strength) + 0.5); 40 int s = (int) (Math.Pow(2, strength) + 0.5);
40 41
41 int x; 42 int x, y;
42 int xFrom = (int)(rx-s+0.5);
43 int xTo = (int)(rx+s+0.5) + 1;
44 int yFrom = (int)(ry-s+0.5);
45 int yTo = (int)(ry+s+0.5) + 1;
46 43
47 if (xFrom < 0) 44 for (x = startX; x <= endX; x++)
48 xFrom = 0;
49
50 if (yFrom < 0)
51 yFrom = 0;
52
53 if (xTo > map.Width)
54 xTo = map.Width;
55
56 if (yTo > map.Width)
57 yTo = map.Width;
58
59 for (x = xFrom; x < xTo; x++)
60 { 45 {
61 int y; 46 for (y = startY; y <= endY; y++)
62 for (y = yFrom; y < yTo; y++)
63 { 47 {
64 if (!mask[x,y]) 48 if (!mask[x, y])
65 continue; 49 continue;
66 50
67 // Calculate a cos-sphere and add it to the heighmap 51 // Calculate a cos-sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
index e7df3f8..46d47b4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
@@ -35,17 +35,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 { 35 {
36 #region ITerrainPaintableEffect Members 36 #region ITerrainPaintableEffect Members
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength); 41 strength = TerrainUtil.MetersToSphericalStrength(strength);
41 42
42 int x; 43 int x, y;
43 for (x = 0; x < map.Width; x++) 44
45 for (x = startX; x <= endX; x++)
44 { 46 {
45 int y; 47 for (y = startY; y <= endY; y++)
46 for (y = 0; y < map.Height; y++)
47 { 48 {
48 if (!mask[x,y]) 49 if (!mask[x, y])
49 continue; 50 continue;
50 51
51 // Calculate a sphere and add it to the heighmap 52 // Calculate a sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
index b199df3..281690d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
@@ -152,18 +152,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
152 152
153 #region ITerrainPaintableEffect Members 153 #region ITerrainPaintableEffect Members
154 154
155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
156 double strength, double duration, int startX, int endX, int startY, int endY)
156 { 157 {
157 strength = TerrainUtil.MetersToSphericalStrength(strength); 158 strength = TerrainUtil.MetersToSphericalStrength(strength);
158 159
159 int x; 160 int x, y;
160 161
161 for (x = 0; x < map.Width; x++) 162 for (x = startX; x <= endX; x++)
162 { 163 {
163 int y; 164 for (y = startY; y <= endY; y++)
164 for (y = 0; y < map.Height; y++)
165 { 165 {
166 if (!mask[x,y]) 166 if (!mask[x, y])
167 continue; 167 continue;
168 168
169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
index bd9a8a0..1b704bb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
@@ -35,38 +35,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 int s = (int) (Math.Pow(2, strength) + 0.5); 41 int s = (int) (Math.Pow(2, strength) + 0.5);
41 42
42 int x; 43 int x,y;
43 int xFrom = (int)(rx-s+0.5);
44 int xTo = (int)(rx+s+0.5) + 1;
45 int yFrom = (int)(ry-s+0.5);
46 int yTo = (int)(ry+s+0.5) + 1;
47 44
48 if (xFrom < 0) 45 for (x = startX; x <= endX; x++)
49 xFrom = 0;
50
51 if (yFrom < 0)
52 yFrom = 0;
53
54 if (xTo > map.Width)
55 xTo = map.Width;
56
57 if (yTo > map.Width)
58 yTo = map.Width;
59
60 for (x = xFrom; x < xTo; x++)
61 { 46 {
62 int y; 47 for (y = startY; y <= endY; y++)
63 for (y = yFrom; y < yTo; y++)
64 { 48 {
65 if (!mask[x,y]) 49 if (!mask[x, y])
66 continue; 50 continue;
67 51
68 // Calculate a cos-sphere and add it to the heighmap 52 // Calculate a cos-sphere and add it to the heighmap
69 double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); 53 double r = Math.Sqrt((x - rx) * (x - rx) + ((y - ry) * (y - ry)));
70 double z = Math.Cos(r * Math.PI / (s * 2)); 54 double z = Math.Cos(r * Math.PI / (s * 2));
71 if (z > 0.0) 55 if (z > 0.0)
72 map[x, y] += z * duration; 56 map[x, y] += z * duration;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
index 4b28275..efc5324 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
@@ -41,7 +41,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
41 41
42 #region ITerrainPaintableEffect Members 42 #region ITerrainPaintableEffect Members
43 43
44 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 44 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
45 double strength, double duration, int startX, int endX, int startY, int endY)
45 { 46 {
46 strength = TerrainUtil.MetersToSphericalStrength(strength); 47 strength = TerrainUtil.MetersToSphericalStrength(strength);
47 duration = 0.03; //MCP Should be read from ini file 48 duration = 0.03; //MCP Should be read from ini file
@@ -51,13 +52,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
51 if (duration < 0) 52 if (duration < 0)
52 return; 53 return;
53 54
54 int x; 55 int x,y;
55 for (x = 0; x < map.Width; x++) 56 for (x = startX; x <= endX; x++)
56 { 57 {
57 int y; 58 for (y = startY; y <= endY; y++)
58 for (y = 0; y < map.Height; y++)
59 { 59 {
60 if (!mask[x,y]) 60 if (!mask[x, y])
61 continue; 61 continue;
62 62
63 // Calculate a sphere and add it to the heighmap 63 // Calculate a sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
index 4834c86..65dd0a6 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
@@ -34,7 +34,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
38 double strength, double duration, int startX, int endX, int startY, int endY)
38 { 39 {
39 strength = TerrainUtil.MetersToSphericalStrength(strength); 40 strength = TerrainUtil.MetersToSphericalStrength(strength);
40 41
@@ -47,10 +48,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
47 48
48 49
49 // compute delta map 50 // compute delta map
50 for (x = 0; x < map.Width; x++) 51 for (x = startX; x <= endX; x++)
51 { 52 {
52 for (y = 0; y < map.Height; y++) 53 for (y = startY; y <= endY; y++)
53 { 54 {
55 if (!mask[x, y])
56 continue;
57
54 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 58 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
55 59
56 if (z > 0) // add in non-zero amount 60 if (z > 0) // add in non-zero amount
@@ -73,11 +77,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
73 } 77 }
74 } 78 }
75 // blend in map 79 // blend in map
76 for (x = 0; x < map.Width; x++) 80 for (x = startX; x <= endX; x++)
77 { 81 {
78 for (y = 0; y < map.Height; y++) 82 for (y = startY; y <= endY; y++)
79 { 83 {
80 if (!mask[x,y]) 84 if (!mask[x, y])
81 continue; 85 continue;
82 86
83 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 87 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
index f31c8b6..f52fe07 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
@@ -148,16 +148,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
148 148
149 #region ITerrainPaintableEffect Members 149 #region ITerrainPaintableEffect Members
150 150
151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
152 double strength, double duration, int startX, int endX, int startY, int endY)
152 { 153 {
153 strength = TerrainUtil.MetersToSphericalStrength(strength); 154 strength = TerrainUtil.MetersToSphericalStrength(strength);
154 155
155 int x; 156 int x,y;
156 157
157 for (x = 0; x < map.Width; x++) 158 for (x = startX; x <= endX; x++)
158 { 159 {
159 int y; 160 for (y = startY; y <= endY; y++)
160 for (y = 0; y < map.Height; y++)
161 { 161 {
162 if (!mask[x,y]) 162 if (!mask[x,y])
163 continue; 163 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
index 7ebd08e..c6e992f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
@@ -370,9 +370,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
370 } 370 }
371 return mask; 371 return mask;
372 } 372 }
373
374
375 } 373 }
376
377} 374}
378 375
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 932652c..5e35d95 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Net; 31using System.Net;
32using System.Threading;
32 33
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
@@ -36,7 +37,6 @@ using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using Mono.Addins; 38using Mono.Addins;
38 39
39using OpenSim.Data;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
@@ -86,14 +86,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); 86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
89 private Dictionary<string, ITerrainEffect> m_plugineffects;
90 private Dictionary<string, ITerrainModifier> m_modifyOperations = 89 private Dictionary<string, ITerrainModifier> m_modifyOperations =
91 new Dictionary<string, ITerrainModifier>(); 90 new Dictionary<string, ITerrainModifier>();
91 private Dictionary<string, ITerrainEffect> m_plugineffects;
92 private ITerrainChannel m_channel; 92 private ITerrainChannel m_channel;
93 private ITerrainChannel m_revert; 93 private ITerrainChannel m_baked;
94 private Scene m_scene; 94 private Scene m_scene;
95 private volatile bool m_tainted; 95 private volatile bool m_tainted;
96 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 96
97 private String m_InitialTerrain = "pinhead-island"; 97 private String m_InitialTerrain = "pinhead-island";
98 98
99 // If true, send terrain patch updates to clients based on their view distance 99 // If true, send terrain patch updates to clients based on their view distance
@@ -107,13 +107,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
107 private bool[,] updated; // for each patch, whether it needs to be sent to this client 107 private bool[,] updated; // for each patch, whether it needs to be sent to this client
108 private int updateCount; // number of patches that need to be sent 108 private int updateCount; // number of patches that need to be sent
109 public ScenePresence Presence; // a reference to the client to send to 109 public ScenePresence Presence; // a reference to the client to send to
110 public TerrainData Terrain; // reference to the underlying terrain 110 public bool sendAll;
111 public int sendAllcurrentX;
112 public int sendAllcurrentY;
113
114
111 public PatchUpdates(TerrainData terrData, ScenePresence pPresence) 115 public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
112 { 116 {
113 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize]; 117 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
114 updateCount = 0; 118 updateCount = 0;
115 Presence = pPresence; 119 Presence = pPresence;
116 Terrain = terrData;
117 // Initially, send all patches to the client 120 // Initially, send all patches to the client
118 SetAll(true); 121 SetAll(true);
119 } 122 }
@@ -146,12 +149,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
146 public void SetAll(bool state) 149 public void SetAll(bool state)
147 { 150 {
148 updateCount = 0; 151 updateCount = 0;
149 for(int xx = 0; xx < updated.GetLength(0); xx++) 152 for (int xx = 0; xx < updated.GetLength(0); xx++)
150 for(int yy = 0; yy < updated.GetLength(1); yy++) 153 for (int yy = 0; yy < updated.GetLength(1); yy++)
151 updated[xx, yy] = state; 154 updated[xx, yy] = state;
152 if (state) 155 if (state)
153 updateCount = updated.GetLength(0) * updated.GetLength(1); 156 updateCount = updated.GetLength(0) * updated.GetLength(1);
157 sendAllcurrentX = 0;
158 sendAllcurrentY = 0;
159 sendAll = true;
154 } 160 }
161
155 // Logically OR's the terrain data's patch taint map into this client's update map. 162 // Logically OR's the terrain data's patch taint map into this client's update map.
156 public void SetAll(TerrainData terrData) 163 public void SetAll(TerrainData terrData)
157 { 164 {
@@ -164,9 +171,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
164 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) 171 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
165 ); 172 );
166 } 173 }
167 for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) 174
175 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
168 { 176 {
169 for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) 177 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
170 { 178 {
171 // Only set tainted. The patch bit may be set if the patch was to be sent later. 179 // Only set tainted. The patch bit may be set if the patch was to be sent later.
172 if (terrData.IsTaintedAt(xx, yy, false)) 180 if (terrData.IsTaintedAt(xx, yy, false))
@@ -210,7 +218,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
210 if (terrainConfig != null) 218 if (terrainConfig != null)
211 { 219 {
212 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 220 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
213 m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance); 221 m_sendTerrainUpdatesByViewDistance =
222 terrainConfig.GetBoolean(
223 "SendTerrainUpdatesByViewDistance",m_sendTerrainUpdatesByViewDistance);
214 } 224 }
215 } 225 }
216 226
@@ -227,12 +237,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
227 (int)m_scene.RegionInfo.RegionSizeY, 237 (int)m_scene.RegionInfo.RegionSizeY,
228 (int)m_scene.RegionInfo.RegionSizeZ); 238 (int)m_scene.RegionInfo.RegionSizeZ);
229 m_scene.Heightmap = m_channel; 239 m_scene.Heightmap = m_channel;
230 UpdateRevertMap(); 240
241 UpdateBakedMap();
231 } 242 }
232 else 243 else
233 { 244 {
234 m_channel = m_scene.Heightmap; 245 m_channel = m_scene.Heightmap;
235 UpdateRevertMap(); 246 UpdateBakedMap();
236 } 247 }
237 248
238 m_scene.RegisterModuleInterface<ITerrainModule>(this); 249 m_scene.RegisterModuleInterface<ITerrainModule>(this);
@@ -240,7 +251,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
240 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed; 251 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
241 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 252 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
242 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; 253 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
243 m_scene.EventManager.OnFrame += EventManager_OnFrame; 254 m_scene.EventManager.OnTerrainCheckUpdates += EventManager_TerrainCheckUpdates;
244 } 255 }
245 256
246 InstallDefaultEffects(); 257 InstallDefaultEffects();
@@ -279,7 +290,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
279 // remove the commands 290 // remove the commands
280 m_scene.UnregisterModuleCommander(m_commander.Name); 291 m_scene.UnregisterModuleCommander(m_commander.Name);
281 // remove the event-handlers 292 // remove the event-handlers
282 m_scene.EventManager.OnFrame -= EventManager_OnFrame; 293
294 m_scene.EventManager.OnTerrainCheckUpdates -= EventManager_TerrainCheckUpdates;
283 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; 295 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
284 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; 296 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
285 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; 297 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
@@ -334,7 +346,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
334 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); 346 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
335 m_scene.Heightmap = channel; 347 m_scene.Heightmap = channel;
336 m_channel = channel; 348 m_channel = channel;
337 UpdateRevertMap(); 349 UpdateBakedMap();
338 } 350 }
339 catch(NotImplementedException) 351 catch(NotImplementedException)
340 { 352 {
@@ -426,7 +438,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
426 { 438 {
427 ITerrainChannel channel = loader.Value.LoadStream(stream); 439 ITerrainChannel channel = loader.Value.LoadStream(stream);
428 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 440 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
429 UpdateRevertMap(); 441 UpdateBakedMap();
430 } 442 }
431 catch(NotImplementedException) 443 catch(NotImplementedException)
432 { 444 {
@@ -506,12 +518,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
506 518
507 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 519 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
508 // ITerrainModule.TaintTerrain() 520 // ITerrainModule.TaintTerrain()
509 public void TaintTerrain() 521 public void TaintTerrain ()
510 { 522 {
511 lock(m_perClientPatchUpdates) 523 lock (m_perClientPatchUpdates)
512 { 524 {
513 // Set the flags for all clients so the tainted patches will be sent out 525 // Set the flags for all clients so the tainted patches will be sent out
514 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 526 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
515 { 527 {
516 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 528 pups.SetAll(m_scene.Heightmap.GetTerrainData());
517 } 529 }
@@ -521,13 +533,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
521 // ITerrainModule.PushTerrain() 533 // ITerrainModule.PushTerrain()
522 public void PushTerrain(IClientAPI pClient) 534 public void PushTerrain(IClientAPI pClient)
523 { 535 {
524 // If view distance based, set the modified patch bits and the frame event will send the updates
525 if (m_sendTerrainUpdatesByViewDistance) 536 if (m_sendTerrainUpdatesByViewDistance)
526 { 537 {
527 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 538 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
528 if (presence != null) 539 if (presence != null)
529 { 540 {
530 lock(m_perClientPatchUpdates) 541 lock (m_perClientPatchUpdates)
531 { 542 {
532 PatchUpdates pups; 543 PatchUpdates pups;
533 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 544 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -536,7 +547,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
536 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence); 547 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
537 m_perClientPatchUpdates.Add(presence.UUID, pups); 548 m_perClientPatchUpdates.Add(presence.UUID, pups);
538 } 549 }
539 // By setting all to modified, the next update tick will send the patches
540 pups.SetAll(true); 550 pups.SetAll(true);
541 } 551 }
542 } 552 }
@@ -547,6 +557,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
547 pClient.SendLayerData(new float[10]); 557 pClient.SendLayerData(new float[10]);
548 } 558 }
549 } 559 }
560
550 #region Plugin Loading Methods 561 #region Plugin Loading Methods
551 562
552 private void LoadPlugins() 563 private void LoadPlugins()
@@ -636,7 +647,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
636 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere(); 647 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere();
637 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere(); 648 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere();
638 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere(); 649 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere();
639 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert); 650 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
640 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere(); 651 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere();
641 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere(); 652 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere();
642 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere(); 653 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere();
@@ -647,9 +658,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
647 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea(); 658 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea();
648 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea(); 659 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea();
649 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); 660 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
650 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); 661 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
651 662
652 // Terrain Modifier operations 663 // Terrain Modifier operations
664
653 m_modifyOperations["min"] = new MinModifier(this); 665 m_modifyOperations["min"] = new MinModifier(this);
654 m_modifyOperations["max"] = new MaxModifier(this); 666 m_modifyOperations["max"] = new MaxModifier(this);
655 m_modifyOperations["raise"] = new RaiseModifier(this); 667 m_modifyOperations["raise"] = new RaiseModifier(this);
@@ -673,22 +685,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
673 } 685 }
674 686
675 /// <summary> 687 /// <summary>
676 /// Saves the current state of the region into the revert map buffer. 688 /// Saves the current state of the region into the baked map buffer.
689
677 /// </summary> 690 /// </summary>
678 public void UpdateRevertMap() 691 public void UpdateBakedMap()
679 { 692 {
680 /* 693 m_baked = m_channel.MakeCopy();
681 int x; 694 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
682 for (x = 0; x < m_channel.Width; x++) 695 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
683 {
684 int y;
685 for (y = 0; y < m_channel.Height; y++)
686 {
687 m_revert[x, y] = m_channel[x, y];
688 }
689 }
690 */
691 m_revert = m_channel.MakeCopy();
692 } 696 }
693 697
694 /// <summary> 698 /// <summary>
@@ -715,11 +719,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
715 { 719 {
716 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 720 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
717 fileWidth, fileHeight, 721 fileWidth, fileHeight,
718 (int)m_scene.RegionInfo.RegionSizeX, 722 (int) m_scene.RegionInfo.RegionSizeX,
719 (int)m_scene.RegionInfo.RegionSizeY); 723 (int) m_scene.RegionInfo.RegionSizeY);
720 m_scene.Heightmap = channel; 724 m_scene.Heightmap = channel;
721 m_channel = channel; 725 m_channel = channel;
722 UpdateRevertMap(); 726 UpdateBakedMap();
723 } 727 }
724 728
725 return; 729 return;
@@ -781,39 +785,54 @@ namespace OpenSim.Region.CoreModules.World.Terrain
781 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave); 785 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave);
782 } 786 }
783 787
788
784 /// <summary> 789 /// <summary>
785 /// Called before processing of every simulation frame.
786 /// This is used to check to see of any of the terrain is tainted and, if so, schedule 790 /// This is used to check to see of any of the terrain is tainted and, if so, schedule
787 /// updates for all the presences. 791 /// updates for all the presences.
788 /// This also checks to see if there are updates that need to be sent for each presence. 792 /// This also checks to see if there are updates that need to be sent for each presence.
789 /// This is where the logic is to send terrain updates to clients. 793 /// This is where the logic is to send terrain updates to clients.
790 /// </summary> 794 /// </summary>
791 private void EventManager_OnFrame() 795 /// doing it async, since currently this is 2 heavy for heartbeat
796 private void EventManager_TerrainCheckUpdates()
792 { 797 {
793 TerrainData terrData = m_channel.GetTerrainData(); 798 Util.FireAndForget(
799 EventManager_TerrainCheckUpdatesAsync);
800 }
794 801
795 bool shouldTaint = false; 802 object TerrainCheckUpdatesLock = new object();
796 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 803
804 private void EventManager_TerrainCheckUpdatesAsync(object o)
805 {
806 // dont overlap execution
807 if(Monitor.TryEnter(TerrainCheckUpdatesLock))
797 { 808 {
798 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 809 // this needs fixing
810 TerrainData terrData = m_channel.GetTerrainData();
811
812 bool shouldTaint = false;
813 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
799 { 814 {
800 if (terrData.IsTaintedAt(x, y)) 815 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
801 { 816 {
802 // Found a patch that was modified. Push this flag into the clients. 817 if (terrData.IsTaintedAt(x, y,true))
803 SendToClients(terrData, x, y); 818 {
804 shouldTaint = true; 819 // Found a patch that was modified. Push this flag into the clients.
820 SendToClients(terrData, x, y);
821 shouldTaint = true;
822 }
805 } 823 }
806 } 824 }
807 }
808 825
809 // This event also causes changes to be sent to the clients 826 // This event also causes changes to be sent to the clients
810 CheckSendingPatchesToClients(); 827 CheckSendingPatchesToClients();
811 828
812 // If things changes, generate some events 829 // If things changes, generate some events
813 if (shouldTaint) 830 if (shouldTaint)
814 { 831 {
815 m_scene.EventManager.TriggerTerrainTainted(); 832 m_scene.EventManager.TriggerTerrainTainted();
816 m_tainted = true; 833 m_tainted = true;
834 }
835 Monitor.Exit(TerrainCheckUpdatesLock);
817 } 836 }
818 } 837 }
819 838
@@ -883,11 +902,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
883 presence.ControllingClient.OnLandUndo -= client_OnLandUndo; 902 presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
884 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 903 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
885 } 904 }
886 905 lock (m_perClientPatchUpdates)
887 lock(m_perClientPatchUpdates)
888 m_perClientPatchUpdates.Remove(client); 906 m_perClientPatchUpdates.Remove(client);
889 } 907 }
890 908
891 /// <summary> 909 /// <summary>
892 /// Scan over changes in the terrain and limit height changes. This enforces the 910 /// Scan over changes in the terrain and limit height changes. This enforces the
893 /// non-estate owner limits on rate of terrain editting. 911 /// non-estate owner limits on rate of terrain editting.
@@ -898,12 +916,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
898 TerrainData terrData = m_channel.GetTerrainData(); 916 TerrainData terrData = m_channel.GetTerrainData();
899 917
900 bool wasLimited = false; 918 bool wasLimited = false;
901 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 919 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
902 { 920 {
903 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 921 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
904 { 922 {
905 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 923 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
906 { 924 {
907 // If we should respect the estate settings then 925 // If we should respect the estate settings then
908 // fixup and height deltas that don't respect them. 926 // fixup and height deltas that don't respect them.
909 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 927 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -926,13 +944,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
926 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; 944 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
927 945
928 // loop through the height map for this patch and compare it against 946 // loop through the height map for this patch and compare it against
929 // the revert map 947 // the baked map
930 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 948 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
931 { 949 {
932 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 950 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
933 { 951 {
934 float requestedHeight = terrData[x, y]; 952 float requestedHeight = terrData[x, y];
935 float bakedHeight = (float)m_revert[x, y]; 953 float bakedHeight = (float)m_baked[x, y];
936 float requestedDelta = requestedHeight - bakedHeight; 954 float requestedDelta = requestedHeight - bakedHeight;
937 955
938 if (requestedDelta > maxDelta) 956 if (requestedDelta > maxDelta)
@@ -953,15 +971,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
953 971
954 private void client_OnLandUndo(IClientAPI client) 972 private void client_OnLandUndo(IClientAPI client)
955 { 973 {
956 lock(m_undo)
957 {
958 if (m_undo.Count > 0)
959 {
960 LandUndoState goback = m_undo.Pop();
961 if (goback != null)
962 goback.PlaybackState();
963 }
964 }
965 } 974 }
966 975
967 /// <summary> 976 /// <summary>
@@ -975,19 +984,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
975 if (m_sendTerrainUpdatesByViewDistance) 984 if (m_sendTerrainUpdatesByViewDistance)
976 { 985 {
977 // Add that this patch needs to be sent to the accounting for each client. 986 // Add that this patch needs to be sent to the accounting for each client.
978 lock(m_perClientPatchUpdates) 987 lock (m_perClientPatchUpdates)
979 { 988 {
980 m_scene.ForEachScenePresence(presence => 989 m_scene.ForEachScenePresence(presence =>
981 {
982 PatchUpdates thisClientUpdates;
983 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
984 { 990 {
985 // There is a ScenePresence without a send patch map. Create one. 991 PatchUpdates thisClientUpdates;
986 thisClientUpdates = new PatchUpdates(terrData, presence); 992 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); 993 {
994 // There is a ScenePresence without a send patch map. Create one.
995 thisClientUpdates = new PatchUpdates(terrData, presence);
996 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
997 }
998 thisClientUpdates.SetByXY(x, y, true);
988 } 999 }
989 thisClientUpdates.SetByXY(x, y, true);
990 }
991 ); 1000 );
992 } 1001 }
993 } 1002 }
@@ -998,7 +1007,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
998 //float[] heightMap = terrData.GetFloatsSerialized(); 1007 //float[] heightMap = terrData.GetFloatsSerialized();
999 float[] heightMap = new float[10]; 1008 float[] heightMap = new float[10];
1000 m_scene.ForEachClient( 1009 m_scene.ForEachClient(
1001 delegate(IClientAPI controller) 1010 delegate (IClientAPI controller)
1002 { 1011 {
1003 controller.SendLayerData(x / Constants.TerrainPatchSize, 1012 controller.SendLayerData(x / Constants.TerrainPatchSize,
1004 y / Constants.TerrainPatchSize, 1013 y / Constants.TerrainPatchSize,
@@ -1013,14 +1022,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1013 public int PatchX; 1022 public int PatchX;
1014 public int PatchY; 1023 public int PatchY;
1015 public float Dist; 1024 public float Dist;
1016
1017 public PatchesToSend(int pX, int pY, float pDist) 1025 public PatchesToSend(int pX, int pY, float pDist)
1018 { 1026 {
1019 PatchX = pX; 1027 PatchX = pX;
1020 PatchY = pY; 1028 PatchY = pY;
1021 Dist = pDist; 1029 Dist = pDist;
1022 } 1030 }
1023
1024 public int CompareTo(PatchesToSend other) 1031 public int CompareTo(PatchesToSend other)
1025 { 1032 {
1026 return Dist.CompareTo(other.Dist); 1033 return Dist.CompareTo(other.Dist);
@@ -1029,119 +1036,224 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1029 1036
1030 // Called each frame time to see if there are any patches to send to any of the 1037 // Called each frame time to see if there are any patches to send to any of the
1031 // ScenePresences. 1038 // ScenePresences.
1032 // We know this is only called if we are doing view distance patch sending so some
1033 // tests are not made.
1034 // Loop through all the per-client info and send any patches necessary. 1039 // Loop through all the per-client info and send any patches necessary.
1035 private void CheckSendingPatchesToClients() 1040 private void CheckSendingPatchesToClients()
1036 { 1041 {
1037 lock(m_perClientPatchUpdates) 1042 lock (m_perClientPatchUpdates)
1038 { 1043 {
1039 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 1044 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
1040 { 1045 {
1046 if(pups.Presence.IsDeleted)
1047 continue;
1048
1049 // limit rate acording to udp land queue state
1050 if (!pups.Presence.ControllingClient.CanSendLayerData())
1051 continue;
1052
1041 if (pups.HasUpdates()) 1053 if (pups.HasUpdates())
1042 { 1054 {
1043 // There is something that could be sent to this client. 1055 if (m_sendTerrainUpdatesByViewDistance)
1044 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1045 if (toSend.Count > 0)
1046 { 1056 {
1047 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}", 1057 // There is something that could be sent to this client.
1048 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName); 1058 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1049 // Sort the patches to send by the distance from the presence 1059 if (toSend.Count > 0)
1050 toSend.Sort();
1051 /* old way that sent individual patches
1052 foreach (PatchesToSend pts in toSend)
1053 { 1060 {
1054 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null); 1061 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1055 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land); 1062 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1056 } 1063 // Sort the patches to send by the distance from the presence
1057 */ 1064 toSend.Sort();
1058 1065 /*
1059 // new way that sends all patches to the protocol so they can be sent in one block 1066 foreach (PatchesToSend pts in toSend)
1060 int[] xPieces = new int[toSend.Count]; 1067 {
1061 int[] yPieces = new int[toSend.Count]; 1068 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1062 float[] patchPieces = new float[toSend.Count * 2]; 1069 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1063 int pieceIndex = 0; 1070 }
1064 foreach(PatchesToSend pts in toSend) 1071 */
1065 { 1072
1066 patchPieces[pieceIndex++] = pts.PatchX; 1073 int[] xPieces = new int[toSend.Count];
1067 patchPieces[pieceIndex++] = pts.PatchY; 1074 int[] yPieces = new int[toSend.Count];
1075 float[] patchPieces = new float[toSend.Count * 2];
1076 int pieceIndex = 0;
1077 foreach (PatchesToSend pts in toSend)
1078 {
1079 patchPieces[pieceIndex++] = pts.PatchX;
1080 patchPieces[pieceIndex++] = pts.PatchY;
1081 }
1082 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
1068 } 1083 }
1069 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces); 1084 if (pups.sendAll && toSend.Count < 1024)
1085 SendAllModifiedPatchs(pups);
1070 } 1086 }
1087 else
1088 SendAllModifiedPatchs(pups);
1071 } 1089 }
1072 } 1090 }
1073 } 1091 }
1074 } 1092 }
1093 private void SendAllModifiedPatchs(PatchUpdates pups)
1094 {
1095 if (!pups.sendAll) // sanity
1096 return;
1097
1098 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1099 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1100
1101 if (pups.sendAllcurrentX >= limitX && pups.sendAllcurrentY >= limitY)
1102 {
1103 pups.sendAll = false;
1104 pups.sendAllcurrentX = 0;
1105 pups.sendAllcurrentY = 0;
1106 return;
1107 }
1108
1109 int npatchs = 0;
1110 List<PatchesToSend> patchs = new List<PatchesToSend>();
1111 int x = pups.sendAllcurrentX;
1112 int y = pups.sendAllcurrentY;
1113 // send it in the order viewer draws it
1114 // even if not best for memory scan
1115 for (; y < limitY; y++)
1116 {
1117 for (; x < limitX; x++)
1118 {
1119 if (pups.GetByPatch(x, y))
1120 {
1121 pups.SetByPatch(x, y, false);
1122 patchs.Add(new PatchesToSend(x, y, 0));
1123 if (++npatchs >= 128)
1124 {
1125 x++;
1126 break;
1127 }
1128 }
1129 }
1130 if (npatchs >= 128)
1131 break;
1132 x = 0;
1133 }
1134
1135 if (x >= limitX && y >= limitY)
1136 {
1137 pups.sendAll = false;
1138 pups.sendAllcurrentX = 0;
1139 pups.sendAllcurrentY = 0;
1140 }
1141 else
1142 {
1143 pups.sendAllcurrentX = x;
1144 pups.sendAllcurrentY = y;
1145 }
1146
1147 npatchs = patchs.Count;
1148 if (npatchs > 0)
1149 {
1150 int[] xPieces = new int[npatchs];
1151 int[] yPieces = new int[npatchs];
1152 float[] patchPieces = new float[npatchs * 2];
1153 int pieceIndex = 0;
1154 foreach (PatchesToSend pts in patchs)
1155 {
1156 patchPieces[pieceIndex++] = pts.PatchX;
1157 patchPieces[pieceIndex++] = pts.PatchY;
1158 }
1159 pups.Presence.ControllingClient.SendLayerData(-npatchs, 0, patchPieces);
1160 }
1161 }
1075 1162
1076 // Compute a list of modified patches that are within our view distance.
1077 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups) 1163 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
1078 { 1164 {
1079 List<PatchesToSend> ret = new List<PatchesToSend>(); 1165 List<PatchesToSend> ret = new List<PatchesToSend>();
1080 1166
1167 int npatchs = 0;
1168
1081 ScenePresence presence = pups.Presence; 1169 ScenePresence presence = pups.Presence;
1082 if (presence == null) 1170 if (presence == null)
1083 return ret; 1171 return ret;
1084 1172
1085 Vector3 presencePos = presence.AbsolutePosition; 1173 float minz = presence.AbsolutePosition.Z;
1086 1174 if (presence.CameraPosition.Z < minz)
1087 // Before this distance check, the whole region just showed up. Adding the distance 1175 minz = presence.CameraPosition.Z;
1088 // check causes different things to happen for the current and adjacent regions. 1176
1089 // So, to keep legacy views, if the region is legacy sized, don't do distance check. 1177 // this limit should be max terrainheight + max draw
1090 bool isLegacySizedRegion = pups.Terrain.SizeX == Constants.RegionSize && pups.Terrain.SizeY == Constants.RegionSize; 1178 if (minz > 1500f)
1091 bool shouldCheckViewDistance = m_sendTerrainUpdatesByViewDistance && !isLegacySizedRegion; 1179 return ret;
1092 1180
1093 int startX = 0; 1181 int DrawDistance = (int)presence.DrawDistance;
1094 int endX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize; 1182
1095 int startY = 0; 1183 DrawDistance = DrawDistance / Constants.TerrainPatchSize;
1096 int endY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize; 1184
1097 1185 int testposX;
1098 // The following only reduces the size of area scanned for updates. Only significant for very large varregions. 1186 int testposY;
1099 if (shouldCheckViewDistance) 1187
1100 { 1188 if (Math.Abs(presence.AbsolutePosition.X - presence.CameraPosition.X) > 30
1101 // Compute the area of patches within our draw distance 1189 || Math.Abs(presence.AbsolutePosition.Y - presence.CameraPosition.Y) > 30)
1102 startX = (((int)(presencePos.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1190 {
1103 startX = Math.Max(startX, 0); 1191 testposX = (int)presence.CameraPosition.X / Constants.TerrainPatchSize;
1104 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1192 testposY = (int)presence.CameraPosition.Y / Constants.TerrainPatchSize;
1105 startY = (((int)(presencePos.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1193 }
1106 startY = Math.Max(startY, 0); 1194 else
1107 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1195 {
1108 endX = (((int)(presencePos.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1196 testposX = (int)presence.AbsolutePosition.X / Constants.TerrainPatchSize;
1109 endX = Math.Max(endX, 0); 1197 testposY = (int)presence.AbsolutePosition.Y / Constants.TerrainPatchSize;
1110 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1198 }
1111 endY = (((int)(presencePos.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1199 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1112 endY = Math.Max(endY, 0); 1200 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1113 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1201
1114 } 1202 // Compute the area of patches within our draw distance
1115 1203 int startX = testposX - DrawDistance;
1116 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, cpos={4}, isChild={5}, start=<{6},{7}>, end=<{8},{9}>", 1204 if (startX < 0)
1117 // LogHeader, m_scene.RegionInfo.RegionName, 1205 startX = 0;
1118 // presence.DrawDistance, presencePos, presence.CameraPosition, 1206 else if (startX >= limitX)
1119 // isLegacySizeChildRegion, 1207 startX = limitX - 1;
1120 // startX, startY, endX, endY); 1208
1121 for(int x = startX; x < endX; x++) 1209 int startY = testposY - DrawDistance;
1122 { 1210 if (startY < 0)
1123 for(int y = startY; y < endY; y++) 1211 startY = 0;
1212 else if (startY >= limitY)
1213 startY = limitY - 1;
1214
1215 int endX = testposX + DrawDistance;
1216 if (endX < 0)
1217 endX = 0;
1218 else if (endX > limitX)
1219 endX = limitX;
1220
1221 int endY = testposY + DrawDistance;
1222 if (endY < 0)
1223 endY = 0;
1224 else if (endY > limitY)
1225 endY = limitY;
1226
1227 int distx;
1228 int disty;
1229 int distsq;
1230
1231 DrawDistance *= DrawDistance;
1232
1233 for (int x = startX; x < endX; x++)
1234 {
1235 for (int y = startY; y < endY; y++)
1124 { 1236 {
1125 //Need to make sure we don't send the same ones over and over
1126 Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
1127 if (pups.GetByPatch(x, y)) 1237 if (pups.GetByPatch(x, y))
1128 { 1238 {
1129 //Check which has less distance, camera or avatar position, both have to be done. 1239 distx = x - testposX;
1130 //Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off 1240 disty = y - testposY;
1131 if (!shouldCheckViewDistance 1241 distsq = distx * distx + disty * disty;
1132 || Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50) 1242 if (distsq < DrawDistance)
1133 || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
1134 { 1243 {
1135 //They can see it, send it to them
1136 pups.SetByPatch(x, y, false); 1244 pups.SetByPatch(x, y, false);
1137 float dist = Vector3.DistanceSquared(presencePos, patchPos); 1245 ret.Add(new PatchesToSend(x, y, (float)distsq));
1138 ret.Add(new PatchesToSend(x, y, dist)); 1246 if (npatchs++ > 1024)
1247 {
1248 y = endY;
1249 x = endX;
1250 }
1139 } 1251 }
1140 } 1252 }
1141 } 1253 }
1142 } 1254 }
1143 return ret; 1255 return ret;
1144 } 1256 }
1145 1257
1146 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action, 1258 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
1147 float north, float west, float south, float east, UUID agentId) 1259 float north, float west, float south, float east, UUID agentId)
@@ -1161,31 +1273,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1161 int zx = (int)(west + 0.5); 1273 int zx = (int)(west + 0.5);
1162 int zy = (int)(north + 0.5); 1274 int zy = (int)(north + 0.5);
1163 1275
1164 int dx; 1276 int startX = zx - n;
1165 for(dx=-n; dx<=n; dx++) 1277 if (startX < 0)
1278 startX = 0;
1279
1280 int startY = zy - n;
1281 if (startY < 0)
1282 startY = 0;
1283
1284 int endX = zx + n;
1285 if (endX >= m_channel.Width)
1286 endX = m_channel.Width - 1;
1287 int endY = zy + n;
1288 if (endY >= m_channel.Height)
1289 endY = m_channel.Height - 1;
1290
1291 int x, y;
1292
1293 for (x = startX; x <= endX; x++)
1166 { 1294 {
1167 int dy; 1295 for (y = startY; y <= endY; y++)
1168 for(dy=-n; dy<=n; dy++)
1169 { 1296 {
1170 int x = zx + dx; 1297 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1171 int y = zy + dy;
1172 if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height)
1173 { 1298 {
1174 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) 1299 allowMask[x, y] = true;
1175 { 1300 allowed = true;
1176 allowMask[x, y] = true;
1177 allowed = true;
1178 }
1179 } 1301 }
1180 } 1302 }
1181 } 1303 }
1182 if (allowed) 1304 if (allowed)
1183 { 1305 {
1184 StoreUndoState(); 1306 StoreUndoState();
1185 m_painteffects[(StandardTerrainEffects)action].PaintEffect( 1307 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
1186 m_channel, allowMask, west, south, height, size, seconds); 1308 m_channel, allowMask, west, south, height, size, seconds,
1309 startX, endX, startY, endY);
1187 1310
1188 //revert changes outside estate limits 1311 //block changes outside estate limits
1189 if (!god) 1312 if (!god)
1190 EnforceEstateLimits(); 1313 EnforceEstateLimits();
1191 } 1314 }
@@ -1202,22 +1325,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1202 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; 1325 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1203 fillArea.Initialize(); 1326 fillArea.Initialize();
1204 1327
1205 int x; 1328 int startX = (int)west;
1206 for(x = 0; x < m_channel.Width; x++) 1329 int startY = (int)south;
1330 int endX = (int)east;
1331 int endY = (int)north;
1332
1333 if (startX < 0)
1334 startX = 0;
1335 else if (startX >= m_channel.Width)
1336 startX = m_channel.Width - 1;
1337
1338 if (endX < 0)
1339 endX = 0;
1340 else if (endX >= m_channel.Width)
1341 endX = m_channel.Width - 1;
1342
1343 if (startY < 0)
1344 startY = 0;
1345 else if (startY >= m_channel.Height)
1346 startY = m_channel.Height - 1;
1347
1348 if (endY < 0)
1349 endY = 0;
1350 else if (endY >= m_channel.Height)
1351 endY = m_channel.Height - 1;
1352
1353
1354 int x, y;
1355
1356 for (x = startX; x <= endX; x++)
1207 { 1357 {
1208 int y; 1358 for (y = startY; y <= endY; y++)
1209 for(y = 0; y < m_channel.Height; y++)
1210 { 1359 {
1211 if (x < east && x > west) 1360 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1212 { 1361 {
1213 if (y < north && y > south) 1362 fillArea[x, y] = true;
1214 { 1363 allowed = true;
1215 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1216 {
1217 fillArea[x, y] = true;
1218 allowed = true;
1219 }
1220 }
1221 } 1364 }
1222 } 1365 }
1223 } 1366 }
@@ -1225,9 +1368,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1225 if (allowed) 1368 if (allowed)
1226 { 1369 {
1227 StoreUndoState(); 1370 StoreUndoState();
1228 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size); 1371 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size,
1372 startX, endX, startY, endY);
1229 1373
1230 //revert changes outside estate limits 1374 //block changes outside estate limits
1231 if (!god) 1375 if (!god)
1232 EnforceEstateLimits(); 1376 EnforceEstateLimits();
1233 } 1377 }
@@ -1260,37 +1404,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1260 1404
1261 private void StoreUndoState() 1405 private void StoreUndoState()
1262 { 1406 {
1263 lock(m_undo)
1264 {
1265 if (m_undo.Count > 0)
1266 {
1267 LandUndoState last = m_undo.Peek();
1268 if (last != null)
1269 {
1270 if (last.Compare(m_channel))
1271 return;
1272 }
1273 }
1274
1275 LandUndoState nUndo = new LandUndoState(this, m_channel);
1276 m_undo.Push(nUndo);
1277 }
1278 } 1407 }
1279 1408
1280 #region Console Commands 1409 #region Console Commands
1281 1410
1282 private void InterfaceLoadFile(Object[] args) 1411 private void InterfaceLoadFile(Object[] args)
1283 { 1412 {
1284 LoadFromFile((string)args[0]); 1413 LoadFromFile((string) args[0]);
1285 } 1414 }
1286 1415
1287 private void InterfaceLoadTileFile(Object[] args) 1416 private void InterfaceLoadTileFile(Object[] args)
1288 { 1417 {
1289 LoadFromFile((string)args[0], 1418 LoadFromFile((string) args[0],
1290 (int)args[1], 1419 (int) args[1],
1291 (int)args[2], 1420 (int) args[2],
1292 (int)args[3], 1421 (int) args[3],
1293 (int)args[4]); 1422 (int) args[4]);
1294 } 1423 }
1295 1424
1296 private void InterfaceSaveFile(Object[] args) 1425 private void InterfaceSaveFile(Object[] args)
@@ -1309,15 +1438,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1309 1438
1310 private void InterfaceBakeTerrain(Object[] args) 1439 private void InterfaceBakeTerrain(Object[] args)
1311 { 1440 {
1312 UpdateRevertMap(); 1441 UpdateBakedMap();
1313 } 1442 }
1314 1443
1315 private void InterfaceRevertTerrain(Object[] args) 1444 private void InterfaceRevertTerrain(Object[] args)
1316 { 1445 {
1317 int x, y; 1446 int x, y;
1318 for(x = 0; x < m_channel.Width; x++) 1447 for (x = 0; x < m_channel.Width; x++)
1319 for(y = 0; y < m_channel.Height; y++) 1448 for (y = 0; y < m_channel.Height; y++)
1320 m_channel[x, y] = m_revert[x, y]; 1449 m_channel[x, y] = m_baked[x, y];
1321 1450
1322 } 1451 }
1323 1452
@@ -1327,9 +1456,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1327 1456
1328 if (direction.ToLower().StartsWith("y")) 1457 if (direction.ToLower().StartsWith("y"))
1329 { 1458 {
1330 for(int x = 0; x < m_channel.Width; x++) 1459 for (int x = 0; x < m_channel.Width; x++)
1331 { 1460 {
1332 for(int y = 0; y < m_channel.Height / 2; y++) 1461 for (int y = 0; y < m_channel.Height / 2; y++)
1333 { 1462 {
1334 double height = m_channel[x, y]; 1463 double height = m_channel[x, y];
1335 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1464 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1341,9 +1470,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1341 } 1470 }
1342 else if (direction.ToLower().StartsWith("x")) 1471 else if (direction.ToLower().StartsWith("x"))
1343 { 1472 {
1344 for(int y = 0; y < m_channel.Height; y++) 1473 for (int y = 0; y < m_channel.Height; y++)
1345 { 1474 {
1346 for(int x = 0; x < m_channel.Width / 2; x++) 1475 for (int x = 0; x < m_channel.Width / 2; x++)
1347 { 1476 {
1348 double height = m_channel[x, y]; 1477 double height = m_channel[x, y];
1349 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1478 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1415,50 +1544,57 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1415 } 1544 }
1416 1545
1417 } 1546 }
1418
1419 } 1547 }
1420 1548
1421 private void InterfaceElevateTerrain(Object[] args) 1549 private void InterfaceElevateTerrain(Object[] args)
1422 { 1550 {
1551 double val = (double)args[0];
1552
1423 int x, y; 1553 int x, y;
1424 for(x = 0; x < m_channel.Width; x++) 1554 for (x = 0; x < m_channel.Width; x++)
1425 for(y = 0; y < m_channel.Height; y++) 1555 for (y = 0; y < m_channel.Height; y++)
1426 m_channel[x, y] += (double)args[0]; 1556 m_channel[x, y] += val;
1427 } 1557 }
1428 1558
1429 private void InterfaceMultiplyTerrain(Object[] args) 1559 private void InterfaceMultiplyTerrain(Object[] args)
1430 { 1560 {
1431 int x, y; 1561 int x, y;
1432 for(x = 0; x < m_channel.Width; x++) 1562 double val = (double)args[0];
1433 for(y = 0; y < m_channel.Height; y++) 1563
1434 m_channel[x, y] *= (double)args[0]; 1564 for (x = 0; x < m_channel.Width; x++)
1565 for (y = 0; y < m_channel.Height; y++)
1566 m_channel[x, y] *= val;
1435 } 1567 }
1436 1568
1437 private void InterfaceLowerTerrain(Object[] args) 1569 private void InterfaceLowerTerrain(Object[] args)
1438 { 1570 {
1439 int x, y; 1571 int x, y;
1440 for(x = 0; x < m_channel.Width; x++) 1572 double val = (double)args[0];
1441 for(y = 0; y < m_channel.Height; y++) 1573
1442 m_channel[x, y] -= (double)args[0]; 1574 for (x = 0; x < m_channel.Width; x++)
1575 for (y = 0; y < m_channel.Height; y++)
1576 m_channel[x, y] -= val;
1443 } 1577 }
1444 1578
1445 public void InterfaceFillTerrain(Object[] args) 1579 public void InterfaceFillTerrain(Object[] args)
1446 { 1580 {
1447 int x, y; 1581 int x, y;
1582 double val = (double)args[0];
1448 1583
1449 for(x = 0; x < m_channel.Width; x++) 1584 for (x = 0; x < m_channel.Width; x++)
1450 for(y = 0; y < m_channel.Height; y++) 1585 for (y = 0; y < m_channel.Height; y++)
1451 m_channel[x, y] = (double)args[0]; 1586 m_channel[x, y] = val;
1452 } 1587 }
1453 1588
1454 private void InterfaceMinTerrain(Object[] args) 1589 private void InterfaceMinTerrain(Object[] args)
1455 { 1590 {
1456 int x, y; 1591 int x, y;
1457 for(x = 0; x < m_channel.Width; x++) 1592 double val = (double)args[0];
1593 for (x = 0; x < m_channel.Width; x++)
1458 { 1594 {
1459 for(y = 0; y < m_channel.Height; y++) 1595 for(y = 0; y < m_channel.Height; y++)
1460 { 1596 {
1461 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1597 m_channel[x, y] = Math.Max(val, m_channel[x, y]);
1462 } 1598 }
1463 } 1599 }
1464 } 1600 }
@@ -1466,11 +1602,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1466 private void InterfaceMaxTerrain(Object[] args) 1602 private void InterfaceMaxTerrain(Object[] args)
1467 { 1603 {
1468 int x, y; 1604 int x, y;
1469 for(x = 0; x < m_channel.Width; x++) 1605 double val = (double)args[0];
1606 for (x = 0; x < m_channel.Width; x++)
1470 { 1607 {
1471 for(y = 0; y < m_channel.Height; y++) 1608 for(y = 0; y < m_channel.Height; y++)
1472 { 1609 {
1473 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1610 m_channel[x, y] = Math.Min(val, m_channel[x, y]);
1474 } 1611 }
1475 } 1612 }
1476 } 1613 }
@@ -1620,9 +1757,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1620 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); 1757 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
1621 1758
1622 Command bakeRegionCommand = 1759 Command bakeRegionCommand =
1623 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); 1760 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions baked map.");
1624 Command revertRegionCommand = 1761 Command revertRegionCommand =
1625 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); 1762 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the baked map terrain into the regions heightmap.");
1626 1763
1627 Command flipCommand = 1764 Command flipCommand =
1628 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis"); 1765 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis");
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 29e80ef..b209b33 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -60,7 +60,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); 60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
61 ITerrainPaintableEffect effect = new RaiseSphere(); 61 ITerrainPaintableEffect effect = new RaiseSphere();
62 62
63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0); 63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
64 0, midRegion - 1,0, (int)Constants.RegionSize -1);
64 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128)."); 65 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
65 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128)."); 66 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
66 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128)."); 67 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
@@ -79,7 +80,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
79 } 80 }
80 effect = new LowerSphere(); 81 effect = new LowerSphere();
81 82
82 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0); 83 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
84 0, (int)Constants.RegionSize -1,0, (int)Constants.RegionSize -1);
83 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); 85 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
84 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); 86 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
85 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128)."); 87 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 9534ad3..4719ba3 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -79,6 +79,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting 79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger. 80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger.
81 /// </remarks> 81 /// </remarks>
82
82 public static Bitmap Splat(ITerrainChannel terrain, 83 public static Bitmap Splat(ITerrainChannel terrain,
83 UUID[] textureIDs, float[] startHeights, float[] heightRanges, 84 UUID[] textureIDs, float[] startHeights, float[] heightRanges,
84 Vector3d regionPosition, IAssetService assetService, bool textureTerrain) 85 Vector3d regionPosition, IAssetService assetService, bool textureTerrain)
@@ -129,8 +130,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
129 asset = assetService.Get(textureIDs[i].ToString()); 130 asset = assetService.Get(textureIDs[i].ToString());
130 if (asset != null) 131 if (asset != null)
131 { 132 {
132// m_log.DebugFormat( 133 // m_log.DebugFormat(
133// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); 134 // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
134 135
135 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 136 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
136 catch (Exception ex) 137 catch (Exception ex)
@@ -140,7 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
140 } 141 }
141 142
142 if (detailTexture[i] != null) 143 if (detailTexture[i] != null)
143 { 144 {
144 // Make sure this texture is the correct size, otherwise resize 145 // Make sure this texture is the correct size, otherwise resize
145 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) 146 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
146 { 147 {
@@ -352,7 +353,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
352 b.Dispose(); 353 b.Dispose();
353 return result; 354 return result;
354 } 355 }
355
356 public static Bitmap SplatSimple(float[] heightmap) 356 public static Bitmap SplatSimple(float[] heightmap)
357 { 357 {
358 const float BASE_HSV_H = 93f / 360f; 358 const float BASE_HSV_H = 93f / 360f;
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 5f2534b..443eee1 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -80,6 +80,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
80 80
81 private bool m_Enabled = false; 81 private bool m_Enabled = false;
82 82
83 private Bitmap lastImage = null;
84 private DateTime lastImageTime = DateTime.MinValue;
85
83 #region Region Module interface 86 #region Region Module interface
84 87
85 public void Initialise(IConfigSource source) 88 public void Initialise(IConfigSource source)
@@ -118,14 +121,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
118 121
119 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 122 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
120 if (renderers.Count > 0) 123 if (renderers.Count > 0)
121 { 124 m_log.Info("[MAPTILE]: Loaded prim mesher " + renderers[0]);
122 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
123 m_log.DebugFormat("[WARP 3D IMAGE MODULE]: Loaded prim mesher {0}", m_primMesher);
124 }
125 else 125 else
126 { 126 m_log.Info("[MAPTILE]: No prim mesher loaded, prim rendering will be disabled");
127 m_log.Debug("[WARP 3D IMAGE MODULE]: No prim mesher loaded, prim rendering will be disabled");
128 }
129 127
130 m_scene.RegisterModuleInterface<IMapImageGenerator>(this); 128 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
131 } 129 }
@@ -158,18 +156,36 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
158 156
159 public Bitmap CreateMapTile() 157 public Bitmap CreateMapTile()
160 { 158 {
161 // Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 159 /* this must be on all map, not just its image
162 // Camera above the middle of the region 160 if ((DateTime.Now - lastImageTime).TotalSeconds < 3600)
161 {
162 return (Bitmap)lastImage.Clone();
163 }
164 */
165
166 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
167 if (renderers.Count > 0)
168 {
169 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
170 }
171
163 Vector3 camPos = new Vector3( 172 Vector3 camPos = new Vector3(
164 m_scene.RegionInfo.RegionSizeX/2 - 0.5f, 173 m_scene.RegionInfo.RegionSizeX / 2 - 0.5f,
165 m_scene.RegionInfo.RegionSizeY/2 - 0.5f, 174 m_scene.RegionInfo.RegionSizeY / 2 - 0.5f,
166 221.7025033688163f); 175 221.7025033688163f);
167 // Viewport viewing down onto the region 176 // Viewport viewing down onto the region
168 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, 177 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
169 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, 178 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
170 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY ); 179 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY);
171 // Fill the viewport and return the image 180
172 return CreateMapTile(viewport, false); 181 Bitmap tile = CreateMapTile(viewport, false);
182 m_primMesher = null;
183 return tile;
184/*
185 lastImage = tile;
186 lastImageTime = DateTime.Now;
187 return (Bitmap)lastImage.Clone();
188 */
173 } 189 }
174 190
175 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 191 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
@@ -285,9 +301,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
285 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 301 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
286 302
287 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f); 303 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
288 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f, 304 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX / 2 - 0.5f,
289 waterHeight, 305 waterHeight,
290 m_scene.RegionInfo.RegionSizeY/2 - 0.5f ); 306 m_scene.RegionInfo.RegionSizeY / 2 - 0.5f);
291 307
292 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); 308 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
293 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif 309 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
@@ -316,7 +332,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
316 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]); 332 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
317 obj.addVertex(new warp_Vertex(pos, 333 obj.addVertex(new warp_Vertex(pos,
318 x / (float)m_scene.RegionInfo.RegionSizeX, 334 x / (float)m_scene.RegionInfo.RegionSizeX,
319 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) ); 335 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY));
320 } 336 }
321 } 337 }
322 338
@@ -384,7 +400,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
384 warp_Texture texture; 400 warp_Texture texture;
385 using ( 401 using (
386 Bitmap image 402 Bitmap image
387 = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges, 403 = TerrainSplat.Splat(
404 terrain, textureIDs, startHeights, heightRanges,
388 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 405 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
389 { 406 {
390 texture = new warp_Texture(image); 407 texture = new warp_Texture(image);
@@ -660,7 +677,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
660 #endregion Rendering Methods 677 #endregion Rendering Methods
661 678
662 #region Static Helpers 679 #region Static Helpers
663
664 // Note: axis change. 680 // Note: axis change.
665 private static warp_Vector ConvertVector(float x, float y, float z) 681 private static warp_Vector ConvertVector(float x, float y, float z)
666 { 682 {
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index d862f18..7370156 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -141,25 +141,23 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
141 141
142 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 142 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
143 { 143 {
144 List<MapBlockData> blocks = new List<MapBlockData>(); 144 Util.FireAndForget(x =>
145 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
146 { 145 {
147 // final block, closing the search result 146 List<MapBlockData> blocks = new List<MapBlockData>();
148 AddFinalBlock(blocks); 147 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
148 {
149 // final block, closing the search result
150 AddFinalBlock(blocks,mapName);
149 151
150 // flags are agent flags sent from the viewer. 152 // flags are agent flags sent from the viewer.
151 // they have different values depending on different viewers, apparently 153 // they have different values depending on different viewers, apparently
152 remoteClient.SendMapBlock(blocks, flags); 154 remoteClient.SendMapBlock(blocks, flags);
153 remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); 155 remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
154 return; 156 return;
155 } 157 }
156 158
159 //m_log.DebugFormat("MAP NAME=({0})", mapName);
157 160
158 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
159
160 string mapNameOrig = mapName;
161 if (regionInfos.Count == 0)
162 {
163 // Hack to get around the fact that ll V3 now drops the port from the 161 // Hack to get around the fact that ll V3 now drops the port from the
164 // map name. See https://jira.secondlife.com/browse/VWR-28570 162 // map name. See https://jira.secondlife.com/browse/VWR-28570
165 // 163 //
@@ -168,69 +166,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
168 // or url encode if possible. 166 // or url encode if possible.
169 // the hacks we do with this viewer... 167 // the hacks we do with this viewer...
170 // 168 //
169 bool needOriginalName = false;
170 string mapNameOrig = mapName;
171 if (mapName.Contains("|")) 171 if (mapName.Contains("|"))
172 {
172 mapName = mapName.Replace('|', ':'); 173 mapName = mapName.Replace('|', ':');
174 needOriginalName = true;
175 }
173 if (mapName.Contains("+")) 176 if (mapName.Contains("+"))
177 {
174 mapName = mapName.Replace('+', ' '); 178 mapName = mapName.Replace('+', ' ');
179 needOriginalName = true;
180 }
175 if (mapName.Contains("!")) 181 if (mapName.Contains("!"))
182 {
176 mapName = mapName.Replace('!', '/'); 183 mapName = mapName.Replace('!', '/');
177 184 needOriginalName = true;
178 if (mapName != mapNameOrig) 185 }
179 regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); 186 if (mapName.Contains("."))
180 } 187 needOriginalName = true;
181 188
182 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags); 189 // try to fetch from GridServer
183 190 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
184 if (regionInfos.Count > 0) 191 // if (regionInfos.Count == 0)
185 { 192 // remoteClient.SendAlertMessage("Hyperlink could not be established.");
186 foreach (GridRegion info in regionInfos) 193
194 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
195
196 MapBlockData data;
197 if (regionInfos.Count > 0)
187 { 198 {
188 if ((flags & 2) == 2) // V2 sends this 199 foreach (GridRegion info in regionInfos)
189 { 200 {
190 List<MapBlockData> datas = WorldMap.Map2BlockFromGridRegion(info, flags); 201 data = new MapBlockData();
191 // ugh! V2-3 is very sensitive about the result being 202 data.Agents = 0;
192 // exactly the same as the requested name 203 data.Access = info.Access;
193 if (regionInfos.Count == 1 && (mapName != mapNameOrig)) 204 MapBlockData block = new MapBlockData();
194 datas.ForEach(d => d.Name = mapNameOrig); 205 WorldMap.MapBlockFromGridRegion(block, info, flags);
195 206
196 blocks.AddRange(datas); 207 if (flags == 2 && regionInfos.Count == 1 && needOriginalName)
197 } 208 block.Name = mapNameOrig;
198 else 209 blocks.Add(block);
199 {
200 MapBlockData data = WorldMap.MapBlockFromGridRegion(info, flags);
201 blocks.Add(data);
202 } 210 }
203 } 211 }
204 }
205 212
206 // final block, closing the search result 213 // final block, closing the search result
207 AddFinalBlock(blocks); 214 AddFinalBlock(blocks,mapNameOrig);
208 215
209 // flags are agent flags sent from the viewer. 216 // flags are agent flags sent from the viewer.
210 // they have different values depending on different viewers, apparently 217 // they have different values depending on different viewers, apparently
211 remoteClient.SendMapBlock(blocks, flags); 218 remoteClient.SendMapBlock(blocks, flags);
212 219
213 // send extra user messages for V3 220 // send extra user messages for V3
214 // because the UI is very confusing 221 // because the UI is very confusing
215 // while we don't fix the hard-coded urls 222 // while we don't fix the hard-coded urls
216 if (flags == 2) 223 if (flags == 2)
217 { 224 {
218 if (regionInfos.Count == 0) 225 if (regionInfos.Count == 0)
219 remoteClient.SendAlertMessage("No regions found with that name."); 226 remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
220 // this seems unnecessary because found regions will show up in the search results 227// else if (regionInfos.Count == 1)
221 //else if (regionInfos.Count == 1) 228// remoteClient.SendAgentAlertMessage("Region found!", false);
222 // remoteClient.SendAlertMessage("Region found!"); 229 }
223 } 230 });
224 } 231 }
225 232
226 private void AddFinalBlock(List<MapBlockData> blocks) 233 private void AddFinalBlock(List<MapBlockData> blocks,string name)
227 { 234 {
228 // final block, closing the search result 235 // final block, closing the search result
229 MapBlockData data = new MapBlockData(); 236 MapBlockData data = new MapBlockData();
230 data.Agents = 0; 237 data.Agents = 0;
231 data.Access = (byte)SimAccess.NonExistent; 238 data.Access = (byte)SimAccess.NonExistent;
232 data.MapImageId = UUID.Zero; 239 data.MapImageId = UUID.Zero;
233 data.Name = ""; 240 data.Name = name;
234 data.RegionFlags = 0; 241 data.RegionFlags = 0;
235 data.WaterHeight = 0; // not used 242 data.WaterHeight = 0; // not used
236 data.X = 0; 243 data.X = 0;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index db1187e..b8645e2 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -68,30 +68,33 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
68 private static readonly UUID STOP_UUID = UUID.Random(); 68 private static readonly UUID STOP_UUID = UUID.Random();
69 private static readonly string m_mapLayerPath = "0001/"; 69 private static readonly string m_mapLayerPath = "0001/";
70 70
71 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
72
73 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
74 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
75
71 private IMapImageGenerator m_mapImageGenerator; 76 private IMapImageGenerator m_mapImageGenerator;
72 private IMapImageUploadModule m_mapImageServiceModule; 77 private IMapImageUploadModule m_mapImageServiceModule;
73 78
74 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
75
76 protected Scene m_scene; 79 protected Scene m_scene;
77 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 80 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
78 private int cachedTime = 0;
79 private int blacklistTimeout = 10*60*1000; // 10 minutes
80 private byte[] myMapImageJPEG; 81 private byte[] myMapImageJPEG;
81 protected volatile bool m_Enabled = false; 82 protected volatile bool m_Enabled = false;
82 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>(); 83 private ExpiringCache<string, int> m_blacklistedurls = new ExpiringCache<string, int>();
83 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 84 private ExpiringCache<ulong, int> m_blacklistedregions = new ExpiringCache<ulong, int>();
84 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 85 private ExpiringCache<ulong, string> m_cachedRegionMapItemsAddress = new ExpiringCache<ulong, string>();
85 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 86 private ExpiringCache<ulong, OSDMap> m_cachedRegionMapItemsResponses =
87 new ExpiringCache<ulong, OSDMap>();
86 private List<UUID> m_rootAgents = new List<UUID>(); 88 private List<UUID> m_rootAgents = new List<UUID>();
87 private volatile bool threadrunning = false; 89 private volatile bool threadrunning = false;
88 90 // expire time for the blacklists in seconds
89 private IServiceThrottleModule m_ServiceThrottle; 91 private double expireBlackListTime = 600.0; // 10 minutes
90 92 // expire mapItems responses time in seconds. Throttles requests to regions that do answer
93 private const double expireResponsesTime = 120.0; // 2 minutes ?
91 //private int CacheRegionsDistance = 256; 94 //private int CacheRegionsDistance = 256;
92 95
93 #region INonSharedRegionModule Members 96 #region INonSharedRegionModule Members
94 public virtual void Initialise (IConfigSource config) 97 public virtual void Initialise(IConfigSource config)
95 { 98 {
96 string[] configSections = new string[] { "Map", "Startup" }; 99 string[] configSections = new string[] { "Map", "Startup" };
97 100
@@ -99,8 +102,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
99 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 102 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
100 m_Enabled = true; 103 m_Enabled = true;
101 104
102 blacklistTimeout 105 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
103 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
104 } 106 }
105 107
106 public virtual void AddRegion(Scene scene) 108 public virtual void AddRegion(Scene scene)
@@ -128,7 +130,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 } 130 }
129 } 131 }
130 132
131 public virtual void RemoveRegion (Scene scene) 133 public virtual void RemoveRegion(Scene scene)
132 { 134 {
133 if (!m_Enabled) 135 if (!m_Enabled)
134 return; 136 return;
@@ -141,13 +143,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
141 } 143 }
142 } 144 }
143 145
144 public virtual void RegionLoaded (Scene scene) 146 public virtual void RegionLoaded(Scene scene)
145 { 147 {
146 if (!m_Enabled) 148 if (!m_Enabled)
147 return; 149 return;
148 150
149 m_ServiceThrottle = scene.RequestModuleInterface<IServiceThrottleModule>();
150
151 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>(); 151 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>();
152 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>(); 152 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>();
153 } 153 }
@@ -179,14 +179,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
179 179
180 MainServer.Instance.AddHTTPHandler(regionimage, 180 MainServer.Instance.AddHTTPHandler(regionimage,
181 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions() 181 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
182 { 182 {
183 AllowXForwardedFor = false, 183 AllowXForwardedFor = false,
184 ForgetTimeSpan = TimeSpan.FromMinutes(2), 184 ForgetTimeSpan = TimeSpan.FromMinutes(2),
185 MaxRequestsInTimeframe = 4, 185 MaxRequestsInTimeframe = 4,
186 ReportingName = "MAPDOSPROTECTOR", 186 ReportingName = "MAPDOSPROTECTOR",
187 RequestTimeSpan = TimeSpan.FromSeconds(10), 187 RequestTimeSpan = TimeSpan.FromSeconds(10),
188 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod 188 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
189 }).Process); 189 }).Process);
190 MainServer.Instance.AddLLSDHandler( 190 MainServer.Instance.AddLLSDHandler(
191 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 191 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
192 192
@@ -197,13 +197,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
197 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 197 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
198 m_scene.EventManager.OnRegionUp += OnRegionUp; 198 m_scene.EventManager.OnRegionUp += OnRegionUp;
199 199
200// StartThread(new object()); 200 StartThread(new object());
201 } 201 }
202 202
203 // this has to be called with a lock on m_scene 203 // this has to be called with a lock on m_scene
204 protected virtual void RemoveHandlers() 204 protected virtual void RemoveHandlers()
205 { 205 {
206// StopThread(); 206 StopThread();
207 207
208 m_scene.EventManager.OnRegionUp -= OnRegionUp; 208 m_scene.EventManager.OnRegionUp -= OnRegionUp;
209 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 209 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -246,6 +246,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
246 public string MapLayerRequest(string request, string path, string param, 246 public string MapLayerRequest(string request, string path, string param,
247 UUID agentID, Caps caps) 247 UUID agentID, Caps caps)
248 { 248 {
249 // not sure about this....
250
249 //try 251 //try
250 // 252 //
251 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", 253 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
@@ -261,54 +263,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
261 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 263 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
262 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 264 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
263 265
264 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 266 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
265 { 267 //{
266 ScenePresence avatarPresence = null; 268 // ScenePresence avatarPresence = null;
267 269
268 m_scene.TryGetScenePresence(agentID, out avatarPresence); 270 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
269 271
270 if (avatarPresence != null) 272 // if (avatarPresence != null)
271 { 273 // {
272 bool lookup = false; 274 // bool lookup = false;
273 275
274 lock (cachedMapBlocks) 276 // lock (cachedMapBlocks)
275 { 277 // {
276 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 278 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
277 { 279 // {
278 List<MapBlockData> mapBlocks; 280 // List<MapBlockData> mapBlocks;
279 281
280 mapBlocks = cachedMapBlocks; 282 // mapBlocks = cachedMapBlocks;
281 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 283 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
282 } 284 // }
283 else 285 // else
284 { 286 // {
285 lookup = true; 287 // lookup = true;
286 } 288 // }
287 } 289 // }
288 if (lookup) 290 // if (lookup)
289 { 291 // {
290 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 292 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
291 293
292 // Get regions that are within 8 regions of here 294 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
293 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 295 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
294 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 8), 296 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
295 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 8), 297 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
296 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 8), 298 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
297 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) ); 299 // foreach (GridRegion r in regions)
298 foreach (GridRegion r in regions) 300 // {
299 { 301 // MapBlockData block = new MapBlockData();
300 MapBlockData block = MapBlockFromGridRegion(r, 0); 302 // MapBlockFromGridRegion(block, r, 0);
301 mapBlocks.Add(block); 303 // mapBlocks.Add(block);
302 } 304 // }
303 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 305 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
304 306
305 lock (cachedMapBlocks) 307 // lock (cachedMapBlocks)
306 cachedMapBlocks = mapBlocks; 308 // cachedMapBlocks = mapBlocks;
307 309
308 cachedTime = Util.UnixTimeSinceEpoch(); 310 // cachedTime = Util.UnixTimeSinceEpoch();
309 } 311 // }
310 } 312 // }
311 } 313 //}
312 314
313 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 315 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
314 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 316 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -334,9 +336,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
334 /// <returns></returns> 336 /// <returns></returns>
335 protected static OSDMapLayer GetOSDMapLayerResponse() 337 protected static OSDMapLayer GetOSDMapLayerResponse()
336 { 338 {
339 // not sure about this.... 2048 or master 5000 and hack above?
340
337 OSDMapLayer mapLayer = new OSDMapLayer(); 341 OSDMapLayer mapLayer = new OSDMapLayer();
338 mapLayer.Right = 5000; 342 mapLayer.Right = 2048;
339 mapLayer.Top = 5000; 343 mapLayer.Top = 2048;
340 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 344 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
341 345
342 return mapLayer; 346 return mapLayer;
@@ -365,6 +369,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
365 { 369 {
366 m_rootAgents.Remove(AgentId); 370 m_rootAgents.Remove(AgentId);
367 } 371 }
372 lock (m_mapBlockRequestEvent)
373 {
374 if (m_mapBlockRequests.ContainsKey(AgentId))
375 m_mapBlockRequests.Remove(AgentId);
376 }
368 } 377 }
369 #endregion 378 #endregion
370 379
@@ -379,14 +388,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
379 if (threadrunning) return; 388 if (threadrunning) return;
380 threadrunning = true; 389 threadrunning = true;
381 390
382// m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); 391 // m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
383 392
384 WorkManager.StartThread( 393 WorkManager.StartThread(
385 process, 394 process,
386 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName), 395 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName),
387 ThreadPriority.BelowNormal, 396 ThreadPriority.BelowNormal,
388 true, 397 true,
389 true); 398 false);
399 WorkManager.StartThread(
400 MapBlockSendThread,
401 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
402 ThreadPriority.BelowNormal,
403 true,
404 false);
390 } 405 }
391 406
392 /// <summary> 407 /// <summary>
@@ -396,13 +411,29 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
396 { 411 {
397 MapRequestState st = new MapRequestState(); 412 MapRequestState st = new MapRequestState();
398 st.agentID = STOP_UUID; 413 st.agentID = STOP_UUID;
399 st.EstateID=0; 414 st.EstateID = 0;
400 st.flags=0; 415 st.flags = 0;
401 st.godlike=false; 416 st.godlike = false;
402 st.itemtype=0; 417 st.itemtype = 0;
403 st.regionhandle=0; 418 st.regionhandle = 0;
404 419
405 requests.Enqueue(st); 420 requests.Enqueue(st);
421
422 MapBlockRequestData req = new MapBlockRequestData();
423
424 req.client = null;
425 req.minX = 0;
426 req.maxX = 0;
427 req.minY = 0;
428 req.maxY = 0;
429 req.flags = 0;
430
431 lock (m_mapBlockRequestEvent)
432 {
433 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
434 m_mapBlockRequests[UUID.Zero].Enqueue(req);
435 m_mapBlockRequestEvent.Set();
436 }
406 } 437 }
407 438
408 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 439 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -415,315 +446,372 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
415 if (!m_rootAgents.Contains(remoteClient.AgentId)) 446 if (!m_rootAgents.Contains(remoteClient.AgentId))
416 return; 447 return;
417 } 448 }
449
450 // local or remote request?
451 if (regionhandle != 0 && regionhandle != m_scene.RegionInfo.RegionHandle)
452 {
453 // its Remote Map Item Request
454 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes.
455 RequestMapItems("", remoteClient.AgentId, flags, EstateID, godlike, itemtype, regionhandle);
456 return;
457 }
458
418 uint xstart = 0; 459 uint xstart = 0;
419 uint ystart = 0; 460 uint ystart = 0;
420 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); 461 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
421 if (itemtype == (int)GridItemType.AgentLocations) 462
463 // its about this region...
464
465 List<mapItemReply> mapitems = new List<mapItemReply>();
466 mapItemReply mapitem = new mapItemReply();
467
468 // viewers only ask for green dots to each region now
469 // except at login with regionhandle 0
470 // possible on some other rare ocasions
471 // use previus hack of sending all items with the green dots
472
473 bool adultRegion;
474 if (regionhandle == 0)
422 { 475 {
423 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 476 switch (itemtype)
424 { 477 {
425 // Just requesting map info about the current, local region 478 case (int)GridItemType.AgentLocations:
426 int tc = Environment.TickCount; 479 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
427 List<mapItemReply> mapitems = new List<mapItemReply>(); 480
428 mapItemReply mapitem = new mapItemReply(); 481 int tc = Environment.TickCount;
429 if (m_scene.GetRootAgentCount() <= 1) 482 if (m_scene.GetRootAgentCount() <= 1)
430 { 483 {
431 mapitem = new mapItemReply( 484 mapitem = new mapItemReply(
432 xstart + 1, 485 xstart + 1,
433 ystart + 1, 486 ystart + 1,
434 UUID.Zero, 487 UUID.Zero,
435 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 488 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
436 0, 0); 489 0, 0);
437 mapitems.Add(mapitem); 490 mapitems.Add(mapitem);
438 } 491 }
439 else 492 else
440 {
441 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
442 { 493 {
494 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
495 {
443 // Don't send a green dot for yourself 496 // Don't send a green dot for yourself
444 if (sp.UUID != remoteClient.AgentId) 497 if (sp.UUID != remoteClient.AgentId)
445 { 498 {
446 mapitem = new mapItemReply( 499 mapitem = new mapItemReply(
447 xstart + (uint)sp.AbsolutePosition.X, 500 xstart + (uint)sp.AbsolutePosition.X,
448 ystart + (uint)sp.AbsolutePosition.Y, 501 ystart + (uint)sp.AbsolutePosition.Y,
449 UUID.Zero, 502 UUID.Zero,
450 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 503 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
451 1, 0); 504 1, 0);
452 mapitems.Add(mapitem); 505 mapitems.Add(mapitem);
453 } 506 }
454 }); 507 });
455 } 508 }
456 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 509 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
457 } 510 break;
458 else
459 {
460 // Remote Map Item Request
461 511
462 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 512 case (int)GridItemType.Telehub:
463 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 513 // Service 1 (MAP_ITEM_TELEHUB)
464 } 514
465 } 515 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
466 else if (itemtype == (int)GridItemType.LandForSale) // Service 7 (MAP_ITEM_LAND_FOR_SALE) 516 if (sog != null)
467 {
468 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
469 {
470 // Parcels
471 ILandChannel landChannel = m_scene.LandChannel;
472 List<ILandObject> parcels = landChannel.AllParcels();
473
474 // Local Map Item Request
475 List<mapItemReply> mapitems = new List<mapItemReply>();
476 mapItemReply mapitem = new mapItemReply();
477 if ((parcels != null) && (parcels.Count >= 1))
478 {
479 foreach (ILandObject parcel_interface in parcels)
480 { 517 {
481 // Play it safe 518 mapitem = new mapItemReply(
482 if (!(parcel_interface is LandObject)) 519 xstart + (uint)sog.AbsolutePosition.X,
483 continue; 520 ystart + (uint)sog.AbsolutePosition.Y,
521 UUID.Zero,
522 sog.Name,
523 0, // color (not used)
524 0 // 0 = telehub / 1 = infohub
525 );
526 mapitems.Add(mapitem);
527 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
528 }
529 break;
484 530
485 LandObject land = (LandObject)parcel_interface; 531 case (int)GridItemType.AdultLandForSale:
486 LandData parcel = land.LandData; 532 case (int)GridItemType.LandForSale:
487 533
488 // Show land for sale 534 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
489 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale) 535 adultRegion = m_scene.RegionInfo.RegionSettings.Maturity == 2;
490 { 536 if (adultRegion)
491 Vector3 min = parcel.AABBMin; 537 {
492 Vector3 max = parcel.AABBMax; 538 if (itemtype == (int)GridItemType.LandForSale)
493 float x = (min.X+max.X)/2; 539 break;
494 float y = (min.Y+max.Y)/2; 540 }
541 else
542 {
543 if (itemtype == (int)GridItemType.AdultLandForSale)
544 break;
545 }
495 546
496 mapitem = new mapItemReply( 547 // Parcels
548 ILandChannel landChannel = m_scene.LandChannel;
549 List<ILandObject> parcels = landChannel.AllParcels();
550
551 if ((parcels != null) && (parcels.Count >= 1))
552 {
553 foreach (ILandObject parcel_interface in parcels)
554 {
555 // Play it safe
556 if (!(parcel_interface is LandObject))
557 continue;
558
559 LandObject land = (LandObject)parcel_interface;
560 LandData parcel = land.LandData;
561
562 // Show land for sale
563 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
564 {
565 Vector3 min = parcel.AABBMin;
566 Vector3 max = parcel.AABBMax;
567 float x = (min.X + max.X) / 2;
568 float y = (min.Y + max.Y) / 2;
569 mapitem = new mapItemReply(
497 xstart + (uint)x, 570 xstart + (uint)x,
498 ystart + (uint)y, 571 ystart + (uint)y,
499 parcel.GlobalID, 572 parcel.GlobalID,
500 parcel.Name, 573 parcel.Name,
501 parcel.Area, 574 parcel.Area,
502 parcel.SalePrice 575 parcel.SalePrice
503 ); 576 );
504 mapitems.Add(mapitem); 577 mapitems.Add(mapitem);
578 }
505 } 579 }
506 } 580 }
507 } 581 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
508 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 582 break;
509 }
510 else
511 {
512 // Remote Map Item Request
513 583
514 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 584 case (uint)GridItemType.PgEvent:
515 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 585 case (uint)GridItemType.MatureEvent:
586 case (uint)GridItemType.AdultEvent:
587 case (uint)GridItemType.Classified:
588 case (uint)GridItemType.Popular:
589 // TODO
590 // just dont not cry about them
591 break;
592
593 default:
594 // unkown map item type
595 m_log.DebugFormat("[WORLD MAP]: Unknown MapItem type {1}", itemtype);
596 break;
516 } 597 }
517 } 598 }
518 else if (itemtype == (int)GridItemType.Telehub) // Service 1 (MAP_ITEM_TELEHUB) 599 else
519 { 600 {
520 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 601 // send all items till we get a better fix
521 {
522 List<mapItemReply> mapitems = new List<mapItemReply>();
523 mapItemReply mapitem = new mapItemReply();
524 602
525 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); 603 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
526 if (sog != null)
527 {
528 mapitem = new mapItemReply(
529 xstart + (uint)sog.AbsolutePosition.X,
530 ystart + (uint)sog.AbsolutePosition.Y,
531 UUID.Zero,
532 sog.Name,
533 0, // color (not used)
534 0 // 0 = telehub / 1 = infohub
535 );
536 mapitems.Add(mapitem);
537 604
538 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 605 int tc = Environment.TickCount;
539 } 606 if (m_scene.GetRootAgentCount() <= 1)
607 {
608 mapitem = new mapItemReply(
609 xstart + 1,
610 ystart + 1,
611 UUID.Zero,
612 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
613 0, 0);
614 mapitems.Add(mapitem);
540 } 615 }
541 else 616 else
542 { 617 {
543 // Remote Map Item Request 618 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
544 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 619 {
620 // Don't send a green dot for yourself
621 if (sp.UUID != remoteClient.AgentId)
622 {
623 mapitem = new mapItemReply(
624 xstart + (uint)sp.AbsolutePosition.X,
625 ystart + (uint)sp.AbsolutePosition.Y,
626 UUID.Zero,
627 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
628 1, 0);
629 mapitems.Add(mapitem);
630 }
631 });
545 } 632 }
546 } 633 remoteClient.SendMapItemReply(mapitems.ToArray(), 6, flags);
547 } 634 mapitems.Clear();
548 635
549 private int nAsyncRequests = 0; 636 // Service 1 (MAP_ITEM_TELEHUB)
550 /// <summary> 637
551 /// Processing thread main() loop for doing remote mapitem requests 638 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
552 /// </summary> 639 if (sog != null)
553 public void process()
554 {
555 //const int MAX_ASYNC_REQUESTS = 20;
556 try
557 {
558 while (true)
559 { 640 {
560 MapRequestState st = requests.Dequeue(1000); 641 mapitem = new mapItemReply(
642 xstart + (uint)sog.AbsolutePosition.X,
643 ystart + (uint)sog.AbsolutePosition.Y,
644 UUID.Zero,
645 sog.Name,
646 0, // color (not used)
647 0 // 0 = telehub / 1 = infohub
648 );
649 mapitems.Add(mapitem);
650 remoteClient.SendMapItemReply(mapitems.ToArray(), 1, flags);
651 mapitems.Clear();
652 }
561 653
562 // end gracefully 654 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
563 if (st.agentID == STOP_UUID)
564 break;
565 655
566 if (st.agentID != UUID.Zero) 656 uint its = 7;
657 if (m_scene.RegionInfo.RegionSettings.Maturity == 2)
658 its = 10;
659
660 // Parcels
661 ILandChannel landChannel = m_scene.LandChannel;
662 List<ILandObject> parcels = landChannel.AllParcels();
663
664 if ((parcels != null) && (parcels.Count >= 1))
665 {
666 foreach (ILandObject parcel_interface in parcels)
567 { 667 {
568 bool dorequest = true; 668 // Play it safe
569 lock (m_rootAgents) 669 if (!(parcel_interface is LandObject))
570 { 670 continue;
571 if (!m_rootAgents.Contains(st.agentID)) 671
572 dorequest = false; 672 LandObject land = (LandObject)parcel_interface;
573 } 673 LandData parcel = land.LandData;
574 674
575 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 675 // Show land for sale
676 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
576 { 677 {
577 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 678 Vector3 min = parcel.AABBMin;
578 Thread.Sleep(80); 679 Vector3 max = parcel.AABBMax;
579 680 float x = (min.X + max.X) / 2;
580 RequestMapItemsDelegate d = RequestMapItemsAsync; 681 float y = (min.Y + max.Y) / 2;
581 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); 682 mapitem = new mapItemReply(
582 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); 683 xstart + (uint)x,
583 //RequestMapItemsCompleted(response); 684 ystart + (uint)y,
584 Interlocked.Increment(ref nAsyncRequests); 685 parcel.GlobalID,
686 parcel.Name,
687 parcel.Area,
688 parcel.SalePrice
689 );
690 mapitems.Add(mapitem);
585 } 691 }
586 } 692 }
587 693 if(mapitems.Count >0)
588 Watchdog.UpdateThread(); 694 remoteClient.SendMapItemReply(mapitems.ToArray(), its, flags);
695 mapitems.Clear();
589 } 696 }
590 } 697 }
591 catch (Exception e)
592 {
593 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
594 }
595
596 threadrunning = false;
597 Watchdog.RemoveThread();
598 } 698 }
599 699
600 const int MAX_ASYNC_REQUESTS = 20; 700 private int nAsyncRequests = 0;
601
602 /// <summary> 701 /// <summary>
603 /// Enqueues the map item request into the services throttle processing thread 702 /// Processing thread main() loop for doing remote mapitem requests
604 /// </summary> 703 /// </summary>
605 /// <param name="state"></param> 704 public void process()
606 public void EnqueueMapItemRequest(MapRequestState st)
607 { 705 {
706 const int MAX_ASYNC_REQUESTS = 20;
707 ScenePresence av = null;
708 MapRequestState st = null;
608 709
609 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate 710 try
610 { 711 {
611 if (st.agentID != UUID.Zero) 712 while (true)
612 { 713 {
613 bool dorequest = true; 714 Watchdog.UpdateThread();
614 lock (m_rootAgents)
615 {
616 if (!m_rootAgents.Contains(st.agentID))
617 dorequest = false;
618 }
619 715
620 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 716 av = null;
621 { 717 st = null;
622 if (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
623 {
624 // AH!!! Recursive !
625 // Put this request back in the queue and return
626 EnqueueMapItemRequest(st);
627 return;
628 }
629 718
630 RequestMapItemsDelegate d = RequestMapItemsAsync; 719 st = requests.Dequeue(4900); // timeout to make watchdog happy
631 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
632 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
633 //RequestMapItemsCompleted(response);
634 Interlocked.Increment(ref nAsyncRequests);
635 }
636 }
637 });
638 }
639 720
640 /// <summary> 721 if (st == null || st.agentID == UUID.Zero)
641 /// Sends the mapitem response to the IClientAPI 722 continue;
642 /// </summary>
643 /// <param name="response">The OSDMap Response for the mapitem</param>
644 private void RequestMapItemsCompleted(IAsyncResult iar)
645 {
646 AsyncResult result = (AsyncResult)iar;
647 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
648 723
649 OSDMap response = (OSDMap)icon.EndInvoke(iar); 724 // end gracefully
725 if (st.agentID == STOP_UUID)
726 break;
650 727
651 Interlocked.Decrement(ref nAsyncRequests); 728 // agent gone?
729
730 m_scene.TryGetScenePresence(st.agentID, out av);
731 if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
732 continue;
652 733
653 if (!response.ContainsKey("requestID")) 734 // region unreachable?
654 return; 735 if (m_blacklistedregions.Contains(st.regionhandle))
736 continue;
655 737
656 UUID requestID = response["requestID"].AsUUID(); 738 bool dorequest = true;
739 OSDMap responseMap = null;
657 740
658 if (requestID != UUID.Zero) 741 // check if we are already serving this region
659 { 742 lock (m_cachedRegionMapItemsResponses)
660 MapRequestState mrs = new MapRequestState();
661 mrs.agentID = UUID.Zero;
662 lock (m_openRequests)
663 {
664 if (m_openRequests.ContainsKey(requestID))
665 { 743 {
666 mrs = m_openRequests[requestID]; 744 if (m_cachedRegionMapItemsResponses.Contains(st.regionhandle))
667 m_openRequests.Remove(requestID); 745 {
746 m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out responseMap);
747 dorequest = false;
748 }
749 else
750 m_cachedRegionMapItemsResponses.Add(st.regionhandle, null, expireResponsesTime); // a bit more time for the access
668 } 751 }
669 }
670 752
671 if (mrs.agentID != UUID.Zero) 753 if (dorequest)
672 {
673 ScenePresence av = null;
674 m_scene.TryGetScenePresence(mrs.agentID, out av);
675 if (av != null)
676 { 754 {
677 if (response.ContainsKey(mrs.itemtype.ToString())) 755 // nothig for region, fire a request
756 Interlocked.Increment(ref nAsyncRequests);
757 MapRequestState rst = st;
758 Util.FireAndForget(x =>
678 { 759 {
679 List<mapItemReply> returnitems = new List<mapItemReply>(); 760 RequestMapItemsAsync(rst.agentID, rst.flags, rst.EstateID, rst.godlike, rst.itemtype, rst.regionhandle);
680 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; 761 });
681 for (int i = 0; i < itemarray.Count; i++) 762 }
682 { 763 else
683 OSDMap mapitem = (OSDMap)itemarray[i]; 764 {
684 mapItemReply mi = new mapItemReply(); 765 // do we have the response?
685 mi.FromOSD(mapitem); 766 if (responseMap != null)
686 returnitems.Add(mi);
687 }
688 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
689 }
690
691 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
692 uint itemtype = (uint)GridItemType.LandForSale;
693
694 if (response.ContainsKey(itemtype.ToString()))
695 { 767 {
696 List<mapItemReply> returnitems = new List<mapItemReply>(); 768 if(av!=null)
697 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
698 for (int i = 0; i < itemarray.Count; i++)
699 { 769 {
700 OSDMap mapitem = (OSDMap)itemarray[i]; 770 // this will mainly only send green dots now
701 mapItemReply mi = new mapItemReply(); 771 if (responseMap.ContainsKey(st.itemtype.ToString()))
702 mi.FromOSD(mapitem); 772 {
703 returnitems.Add(mi); 773 List<mapItemReply> returnitems = new List<mapItemReply>();
774 OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
775 for (int i = 0; i < itemarray.Count; i++)
776 {
777 OSDMap mapitem = (OSDMap)itemarray[i];
778 mapItemReply mi = new mapItemReply();
779 mi.x = (uint)mapitem["X"].AsInteger();
780 mi.y = (uint)mapitem["Y"].AsInteger();
781 mi.id = mapitem["ID"].AsUUID();
782 mi.Extra = mapitem["Extra"].AsInteger();
783 mi.Extra2 = mapitem["Extra2"].AsInteger();
784 mi.name = mapitem["Name"].AsString();
785 returnitems.Add(mi);
786 }
787 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
788 }
704 } 789 }
705 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
706 } 790 }
707 791 else
708 // Service 1 (MAP_ITEM_TELEHUB)
709 itemtype = (uint)GridItemType.Telehub;
710
711 if (response.ContainsKey(itemtype.ToString()))
712 { 792 {
713 List<mapItemReply> returnitems = new List<mapItemReply>(); 793 // request still beeing processed, enqueue it back
714 OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; 794 requests.Enqueue(st);
715 for (int i = 0; i < itemarray.Count; i++) 795 if (requests.Count() < 3)
716 { 796 Thread.Sleep(100);
717 OSDMap mapitem = (OSDMap)itemarray[i];
718 mapItemReply mi = new mapItemReply();
719 mi.FromOSD(mapitem);
720 returnitems.Add(mi);
721 }
722 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
723 } 797 }
724 } 798 }
799
800 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
801 {
802 Thread.Sleep(100);
803 Watchdog.UpdateThread();
804 }
725 } 805 }
726 } 806 }
807
808 catch (Exception e)
809 {
810 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
811 }
812
813 threadrunning = false;
814 Watchdog.RemoveThread();
727 } 815 }
728 816
729 /// <summary> 817 /// <summary>
@@ -746,11 +834,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
746 st.godlike = godlike; 834 st.godlike = godlike;
747 st.itemtype = itemtype; 835 st.itemtype = itemtype;
748 st.regionhandle = regionhandle; 836 st.regionhandle = regionhandle;
749 EnqueueMapItemRequest(st); 837
838 requests.Enqueue(st);
750 } 839 }
751 840
752 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags, 841 uint[] itemTypesForcedSend = new uint[] { 6, 1, 7, 10 }; // green dots, infohub, land sells
753 uint EstateID, bool godlike, uint itemtype, ulong regionhandle); 842
754 /// <summary> 843 /// <summary>
755 /// Does the actual remote mapitem request 844 /// Does the actual remote mapitem request
756 /// This should be called from an asynchronous thread 845 /// This should be called from an asynchronous thread
@@ -765,94 +854,55 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
765 /// <param name="itemtype">passed in from packet</param> 854 /// <param name="itemtype">passed in from packet</param>
766 /// <param name="regionhandle">Region we're looking up</param> 855 /// <param name="regionhandle">Region we're looking up</param>
767 /// <returns></returns> 856 /// <returns></returns>
768 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 857 private void RequestMapItemsAsync(UUID id, uint flags,
769 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 858 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
770 { 859 {
771// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 860 // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
772 861
773 string httpserver = ""; 862 string httpserver = "";
774 bool blacklisted = false; 863 bool blacklisted = false;
775 lock (m_blacklistedregions)
776 {
777 if (m_blacklistedregions.ContainsKey(regionhandle))
778 {
779 if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
780 {
781 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
782 864
783 m_blacklistedregions.Remove(regionhandle); 865 lock (m_blacklistedregions)
784 } 866 blacklisted = m_blacklistedregions.Contains(regionhandle);
785 else
786 blacklisted = true;
787 }
788 }
789 867
790 if (blacklisted) 868 if (blacklisted)
791 return new OSDMap(); 869 {
870 Interlocked.Decrement(ref nAsyncRequests);
871 return;
872 }
792 873
793 UUID requestID = UUID.Random(); 874 UUID requestID = UUID.Random();
794 lock (m_cachedRegionMapItemsAddress) 875 lock (m_cachedRegionMapItemsAddress)
795 { 876 m_cachedRegionMapItemsAddress.TryGetValue(regionhandle, out httpserver);
796 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 877
797 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 878 if (httpserver == null || httpserver.Length == 0)
798 }
799 if (httpserver.Length == 0)
800 { 879 {
801 uint x = 0, y = 0; 880 uint x = 0, y = 0;
802 Util.RegionHandleToWorldLoc(regionhandle, out x, out y); 881 Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
882
803 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 883 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
804 884
805 if (mreg != null) 885 if (mreg != null)
806 { 886 {
807 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); 887 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
808 lock (m_cachedRegionMapItemsAddress) 888 lock (m_cachedRegionMapItemsAddress)
809 { 889 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle, httpserver, 2.0 * expireBlackListTime);
810 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
811 m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver);
812 }
813 }
814 else
815 {
816 lock (m_blacklistedregions)
817 {
818 if (!m_blacklistedregions.ContainsKey(regionhandle))
819 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
820 }
821 //m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString());
822 } 890 }
823 } 891 }
824 892
825 blacklisted = false;
826 lock (m_blacklistedurls) 893 lock (m_blacklistedurls)
827 { 894 {
828 if (m_blacklistedurls.ContainsKey(httpserver)) 895 if (httpserver == null || httpserver.Length == 0 || m_blacklistedurls.Contains(httpserver))
829 { 896 {
830 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) 897 // Can't find the http server or its blocked
831 { 898 lock (m_blacklistedregions)
832 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); 899 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
833 900
834 m_blacklistedurls.Remove(httpserver); 901 Interlocked.Decrement(ref nAsyncRequests);
835 } 902 return;
836 else
837 blacklisted = true;
838 } 903 }
839 } 904 }
840 905
841 // Can't find the http server
842 if (httpserver.Length == 0 || blacklisted)
843 return new OSDMap();
844
845 MapRequestState mrs = new MapRequestState();
846 mrs.agentID = id;
847 mrs.EstateID = EstateID;
848 mrs.flags = flags;
849 mrs.godlike = godlike;
850 mrs.itemtype=itemtype;
851 mrs.regionhandle = regionhandle;
852
853 lock (m_openRequests)
854 m_openRequests.Add(requestID, mrs);
855
856 WebRequest mapitemsrequest = null; 906 WebRequest mapitemsrequest = null;
857 try 907 try
858 { 908 {
@@ -861,132 +911,144 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
861 catch (Exception e) 911 catch (Exception e)
862 { 912 {
863 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 913 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
864 return new OSDMap(); 914 Interlocked.Decrement(ref nAsyncRequests);
915 return;
865 } 916 }
866 917
867 mapitemsrequest.Method = "POST"; 918 mapitemsrequest.Method = "POST";
868 mapitemsrequest.ContentType = "application/xml+llsd"; 919 mapitemsrequest.ContentType = "application/xml+llsd";
869 OSDMap RAMap = new OSDMap();
870 920
921 OSDMap RAMap = new OSDMap();
871 // string RAMapString = RAMap.ToString(); 922 // string RAMapString = RAMap.ToString();
872 OSD LLSDofRAMap = RAMap; // RENAME if this works 923 OSD LLSDofRAMap = RAMap; // RENAME if this works
873 924
874 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); 925 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
926
875 OSDMap responseMap = new OSDMap(); 927 OSDMap responseMap = new OSDMap();
876 responseMap["requestID"] = OSD.FromUUID(requestID);
877 928
878 Stream os = null;
879 try 929 try
880 { // send the Post 930 { // send the Post
881 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send 931 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
882 os = mapitemsrequest.GetRequestStream(); 932 using (Stream os = mapitemsrequest.GetRequestStream())
883 os.Write(buffer, 0, buffer.Length); //Send it 933 os.Write(buffer, 0, buffer.Length); //Send it
884 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver); 934 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
885 } 935 }
886 catch (WebException ex) 936 catch (WebException ex)
887 { 937 {
888 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 938 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
889 responseMap["connect"] = OSD.FromBoolean(false); 939 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
890 lock (m_blacklistedurls) 940 lock (m_blacklistedurls)
891 { 941 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
892 if (!m_blacklistedurls.ContainsKey(httpserver)) 942 lock (m_blacklistedregions)
893 m_blacklistedurls.Add(httpserver, Environment.TickCount); 943 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
894 }
895
896 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
897 944
898 return responseMap; 945 Interlocked.Decrement(ref nAsyncRequests);
946 return;
899 } 947 }
900 catch 948 catch
901 { 949 {
902 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 950 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
903 responseMap["connect"] = OSD.FromBoolean(false); 951 Interlocked.Decrement(ref nAsyncRequests);
904 return responseMap; 952 return;
905 }
906 finally
907 {
908 if (os != null)
909 os.Dispose();
910 } 953 }
911 954
912 string response_mapItems_reply = null; 955 string response_mapItems_reply = null;
913 { 956 { // get the response
914 try 957 try
915 { 958 {
916 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 959 using (WebResponse webResponse = mapitemsrequest.GetResponse())
917 { 960 {
918 if (webResponse != null) 961 if (webResponse != null)
919 { 962 {
920 using (Stream s = webResponse.GetResponseStream()) 963 using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
921 using (StreamReader sr = new StreamReader(s)) 964 {
922 response_mapItems_reply = sr.ReadToEnd().Trim(); 965 response_mapItems_reply = sr.ReadToEnd().Trim();
966 }
923 } 967 }
924 else 968 else
925 { 969 {
926 return new OSDMap(); 970 Interlocked.Decrement(ref nAsyncRequests);
927 } 971 return;
928 } 972 }
973 }
929 } 974 }
930 catch (WebException) 975 catch (WebException)
931 { 976 {
932 responseMap["connect"] = OSD.FromBoolean(false);
933 lock (m_blacklistedurls) 977 lock (m_blacklistedurls)
934 { 978 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
935 if (!m_blacklistedurls.ContainsKey(httpserver)) 979 lock (m_blacklistedregions)
936 m_blacklistedurls.Add(httpserver, Environment.TickCount); 980 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
937 }
938 981
939 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 982 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
940 983
941 return responseMap; 984 Interlocked.Decrement(ref nAsyncRequests);
985 return;
942 } 986 }
943 catch 987 catch
944 { 988 {
945 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 989 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
946 responseMap["connect"] = OSD.FromBoolean(false);
947 lock (m_blacklistedregions) 990 lock (m_blacklistedregions)
948 { 991 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
949 if (!m_blacklistedregions.ContainsKey(regionhandle))
950 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
951 }
952 992
953 return responseMap; 993 Interlocked.Decrement(ref nAsyncRequests);
994 return;
954 } 995 }
955 996
956 OSD rezResponse = null;
957 try 997 try
958 { 998 {
959 rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); 999 responseMap = (OSDMap)OSDParser.DeserializeLLSDXml(response_mapItems_reply);
960
961 responseMap = (OSDMap)rezResponse;
962 responseMap["requestID"] = OSD.FromUUID(requestID);
963 } 1000 }
964 catch (Exception ex) 1001 catch (Exception ex)
965 { 1002 {
966 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 1003 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
967 responseMap["connect"] = OSD.FromBoolean(false);
968
969 lock (m_blacklistedregions) 1004 lock (m_blacklistedregions)
970 { 1005 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
971 if (!m_blacklistedregions.ContainsKey(regionhandle))
972 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
973 }
974 1006
975 return responseMap; 1007 Interlocked.Decrement(ref nAsyncRequests);
1008 return;
976 } 1009 }
977 } 1010 }
978 1011
979 if (!responseMap.ContainsKey(itemtype.ToString())) // remote sim doesnt have the stated region handle 1012 // cache the response that may include other valid items
1013 lock (m_cachedRegionMapItemsResponses)
1014 m_cachedRegionMapItemsResponses.AddOrUpdate(regionhandle, responseMap, expireResponsesTime);
1015
1016 flags &= 0xffff;
1017
1018 if (id != UUID.Zero)
980 { 1019 {
981 m_log.DebugFormat("[WORLD MAP]: Remote sim does not have the stated region. Blacklisting."); 1020 ScenePresence av = null;
982 lock (m_blacklistedregions) 1021 m_scene.TryGetScenePresence(id, out av);
1022 if (av != null && !av.IsChildAgent && !av.IsDeleted && !av.IsInTransit)
983 { 1023 {
984 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1024 // send all the items or viewers will never ask for them, except green dots
985 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 1025 foreach (uint itfs in itemTypesForcedSend)
1026 {
1027 if (responseMap.ContainsKey(itfs.ToString()))
1028 {
1029 List<mapItemReply> returnitems = new List<mapItemReply>();
1030// OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
1031 OSDArray itemarray = (OSDArray)responseMap[itfs.ToString()];
1032 for (int i = 0; i < itemarray.Count; i++)
1033 {
1034 OSDMap mapitem = (OSDMap)itemarray[i];
1035 mapItemReply mi = new mapItemReply();
1036 mi.x = (uint)mapitem["X"].AsInteger();
1037 mi.y = (uint)mapitem["Y"].AsInteger();
1038 mi.id = mapitem["ID"].AsUUID();
1039 mi.Extra = mapitem["Extra"].AsInteger();
1040 mi.Extra2 = mapitem["Extra2"].AsInteger();
1041 mi.name = mapitem["Name"].AsString();
1042 returnitems.Add(mi);
1043 }
1044// av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
1045 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itfs, flags);
1046 }
1047 }
986 } 1048 }
987 } 1049 }
988 1050
989 return responseMap; 1051 Interlocked.Decrement(ref nAsyncRequests);
990 } 1052 }
991 1053
992 /// <summary> 1054 /// <summary>
@@ -996,87 +1058,133 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
996 /// <param name="minY"></param> 1058 /// <param name="minY"></param>
997 /// <param name="maxX"></param> 1059 /// <param name="maxX"></param>
998 /// <param name="maxY"></param> 1060 /// <param name="maxY"></param>
999 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1061 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1062 {
1063 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1064
1065 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1066 }
1067
1068 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1069 {
1070 MapBlockRequestData req = new MapBlockRequestData();
1071
1072 req.client = remoteClient;
1073 req.minX = minX;
1074 req.maxX = maxX;
1075 req.minY = minY;
1076 req.maxY = maxY;
1077 req.flags = flag;
1078
1079 lock (m_mapBlockRequestEvent)
1080 {
1081 if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
1082 m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
1083 m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
1084 m_mapBlockRequestEvent.Set();
1085 }
1086
1087 return new List<MapBlockData>();
1088 }
1089
1090 protected void MapBlockSendThread()
1000 { 1091 {
1001 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 1092 while (true)
1002 { 1093 {
1003 List<MapBlockData> response = new List<MapBlockData>(); 1094 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1004 1095
1005 // this should return one mapblock at most. It is triggered by a click 1096 m_mapBlockRequestEvent.WaitOne();
1006 // on an unloaded square. 1097 lock (m_mapBlockRequestEvent)
1007 // But make sure: Look whether the one we requested is in there
1008 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1009 (int)Util.RegionToWorldLoc((uint)minX), (int)Util.RegionToWorldLoc((uint)maxX),
1010 (int)Util.RegionToWorldLoc((uint)minY), (int)Util.RegionToWorldLoc((uint)maxY) );
1011
1012 m_log.DebugFormat("[WORLD MAP MODULE] RequestMapBlocks min=<{0},{1}>, max=<{2},{3}>, flag={4}, cntFound={5}",
1013 minX, minY, maxX, maxY, flag.ToString("X"), regions.Count);
1014 if (regions != null)
1015 { 1098 {
1016 foreach (GridRegion r in regions) 1099 int total = 0;
1100 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1017 { 1101 {
1018 if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX) 1102 if (q.Count > 0)
1019 && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) ) 1103 thisRunData.Add(q.Dequeue());
1020 { 1104
1021 // found it => add it to response 1105 total += q.Count;
1022 // Version 2 viewers can handle the larger regions
1023 if ((flag & 2) == 2)
1024 response.AddRange(Map2BlockFromGridRegion(r, flag));
1025 else
1026 response.Add(MapBlockFromGridRegion(r, flag));
1027 break;
1028 }
1029 } 1106 }
1107
1108 if (total == 0)
1109 m_mapBlockRequestEvent.Reset();
1030 } 1110 }
1031 1111
1032 if (response.Count == 0) 1112 foreach (MapBlockRequestData req in thisRunData)
1033 { 1113 {
1034 // response still empty => couldn't find the map-tile the user clicked on => tell the client 1114 // Null client stops thread
1035 MapBlockData block = new MapBlockData(); 1115 if (req.client == null)
1036 block.X = (ushort)minX; 1116 return;
1037 block.Y = (ushort)minY; 1117
1038 block.Access = (byte)SimAccess.Down; // means 'simulator is offline' 1118 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1039 // block.Access = (byte)SimAccess.NonExistent;
1040 response.Add(block);
1041 } 1119 }
1042 // The lower 16 bits are an unsigned int16 1120
1043 remoteClient.SendMapBlock(response, flag & 0xffff); 1121 Thread.Sleep(50);
1044 }
1045 else
1046 {
1047 // normal mapblock request. Use the provided values
1048 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1049 } 1122 }
1050 } 1123 }
1051 1124
1052 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1125 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1053 { 1126 {
1127 List<MapBlockData> allBlocks = new List<MapBlockData>();
1054 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1128 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1055 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1129 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1056 (int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)), 1130 minX * (int)Constants.RegionSize,
1057 (int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) ); 1131 maxX * (int)Constants.RegionSize,
1058 //m_log.DebugFormat("{0} GetAndSendBlocks. min=<{1},{2}>, max=<{3},{4}>, cntFound={5}", 1132 minY * (int)Constants.RegionSize,
1059 // LogHeader, minX, minY, maxX, maxY, regions.Count); 1133 maxY * (int)Constants.RegionSize);
1134
1135 // only send a negative answer for a single region request
1136 // corresponding to a click on the map. Current viewers
1137 // keep displaying "loading.." without this
1138 if (regions.Count == 0 && (flag & 0x10000) != 0 && minX == maxX && minY == maxY)
1139 {
1140 MapBlockData block = new MapBlockData();
1141 block.X = (ushort)minX;
1142 block.Y = (ushort)minY;
1143 block.MapImageId = UUID.Zero;
1144 block.Access = (byte)SimAccess.NonExistent;
1145 allBlocks.Add(block);
1146 mapBlocks.Add(block);
1147 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1148 return allBlocks;
1149 }
1150
1151 flag &= 0xffff;
1152
1060 foreach (GridRegion r in regions) 1153 foreach (GridRegion r in regions)
1061 { 1154 {
1062 // Version 2 viewers can handle the larger regions 1155 if (r == null)
1063 if ((flag & 2) == 2) 1156 continue;
1064 mapBlocks.AddRange(Map2BlockFromGridRegion(r, flag)); 1157 MapBlockData block = new MapBlockData();
1065 else 1158 MapBlockFromGridRegion(block, r, flag);
1066 mapBlocks.Add(MapBlockFromGridRegion(r, flag)); 1159 mapBlocks.Add(block);
1160 allBlocks.Add(block);
1161
1162 if (mapBlocks.Count >= 10)
1163 {
1164 remoteClient.SendMapBlock(mapBlocks, flag);
1165 mapBlocks.Clear();
1166 Thread.Sleep(50);
1167 }
1067 } 1168 }
1068 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1169 if (mapBlocks.Count > 0)
1170 remoteClient.SendMapBlock(mapBlocks, flag);
1069 1171
1070 return mapBlocks; 1172 return allBlocks;
1071 } 1173 }
1072 1174
1073 // Fill a passed MapBlockData from a GridRegion 1175 public void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
1074 public MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag)
1075 { 1176 {
1076 MapBlockData block = new MapBlockData(); 1177 if (r == null)
1178 {
1179 // we should not get here ??
1180// block.Access = (byte)SimAccess.Down; this is for a grid reply on r
1181 block.Access = (byte)SimAccess.NonExistent;
1182 block.MapImageId = UUID.Zero;
1183 return;
1184 }
1077 1185
1078 block.Access = r.Access; 1186 block.Access = r.Access;
1079 switch (flag & 0xffff) 1187 switch (flag)
1080 { 1188 {
1081 case 0: 1189 case 0:
1082 block.MapImageId = r.TerrainImage; 1190 block.MapImageId = r.TerrainImage;
@@ -1089,50 +1197,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1089 break; 1197 break;
1090 } 1198 }
1091 block.Name = r.RegionName; 1199 block.Name = r.RegionName;
1092 block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX); 1200 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1093 block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY); 1201 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1094 block.SizeX = (ushort) r.RegionSizeX; 1202 block.SizeX = (ushort)r.RegionSizeX;
1095 block.SizeY = (ushort) r.RegionSizeY; 1203 block.SizeY = (ushort)r.RegionSizeY;
1096 1204
1097 return block;
1098 } 1205 }
1099 1206
1100 public List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag)
1101 {
1102 List<MapBlockData> blocks = new List<MapBlockData>();
1103 MapBlockData block = new MapBlockData();
1104 if (r == null)
1105 {
1106 block.Access = (byte)SimAccess.Down;
1107 block.MapImageId = UUID.Zero;
1108 blocks.Add(block);
1109 }
1110 else
1111 {
1112 block.Access = r.Access;
1113 switch (flag & 0xffff)
1114 {
1115 case 0:
1116 block.MapImageId = r.TerrainImage;
1117 break;
1118 case 2:
1119 block.MapImageId = r.ParcelImage;
1120 break;
1121 default:
1122 block.MapImageId = UUID.Zero;
1123 break;
1124 }
1125 block.Name = r.RegionName;
1126 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1127 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1128 block.SizeX = (ushort)r.RegionSizeX;
1129 block.SizeY = (ushort)r.RegionSizeY;
1130 blocks.Add(block);
1131 }
1132 return blocks;
1133 }
1134
1135
1136 public Hashtable OnHTTPThrottled(Hashtable keysvals) 1207 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1137 { 1208 {
1138 Hashtable reply = new Hashtable(); 1209 Hashtable reply = new Hashtable();
@@ -1145,67 +1216,71 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1145 1216
1146 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1217 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1147 { 1218 {
1148 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1149 Hashtable reply = new Hashtable(); 1219 Hashtable reply = new Hashtable();
1150 int statuscode = 200; 1220 int statuscode = 200;
1151 byte[] jpeg = new byte[0]; 1221 byte[] jpeg = new byte[0];
1152 1222
1153 if (myMapImageJPEG.Length == 0) 1223 if (m_scene.RegionInfo.RegionSettings.TerrainImageID != UUID.Zero)
1154 { 1224 {
1155 MemoryStream imgstream = null; 1225 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1156 Bitmap mapTexture = new Bitmap(1,1);
1157 ManagedImage managedImage;
1158 Image image = (Image)mapTexture;
1159 1226
1160 try 1227 if (myMapImageJPEG.Length == 0)
1161 { 1228 {
1162 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data 1229 MemoryStream imgstream = null;
1230 Bitmap mapTexture = new Bitmap(1, 1);
1231 ManagedImage managedImage;
1232 Image image = (Image)mapTexture;
1233
1234 try
1235 {
1236 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
1163 1237
1164 imgstream = new MemoryStream(); 1238 imgstream = new MemoryStream();
1165 1239
1166 // non-async because we know we have the asset immediately. 1240 // non-async because we know we have the asset immediately.
1167 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString()); 1241 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1168 1242
1169 // Decode image to System.Drawing.Image 1243 // Decode image to System.Drawing.Image
1170 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) 1244 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
1171 { 1245 {
1172 // Save to bitmap 1246 // Save to bitmap
1173 mapTexture = new Bitmap(image); 1247 mapTexture = new Bitmap(image);
1174 1248
1175 EncoderParameters myEncoderParameters = new EncoderParameters(); 1249 EncoderParameters myEncoderParameters = new EncoderParameters();
1176 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); 1250 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
1177 1251
1178 // Save bitmap to stream 1252 // Save bitmap to stream
1179 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); 1253 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
1180 1254
1181 // Write the stream to a byte array for output 1255 // Write the stream to a byte array for output
1182 jpeg = imgstream.ToArray(); 1256 jpeg = imgstream.ToArray();
1183 myMapImageJPEG = jpeg; 1257 myMapImageJPEG = jpeg;
1258 }
1184 } 1259 }
1185 } 1260 catch (Exception)
1186 catch (Exception) 1261 {
1187 { 1262 // Dummy!
1188 // Dummy! 1263 m_log.Warn("[WORLD MAP]: Unable to generate Map image");
1189 m_log.Warn("[WORLD MAP]: Unable to generate Map image"); 1264 }
1190 } 1265 finally
1191 finally 1266 {
1192 { 1267 // Reclaim memory, these are unmanaged resources
1193 // Reclaim memory, these are unmanaged resources 1268 // If we encountered an exception, one or more of these will be null
1194 // If we encountered an exception, one or more of these will be null 1269 if (mapTexture != null)
1195 if (mapTexture != null) 1270 mapTexture.Dispose();
1196 mapTexture.Dispose();
1197 1271
1198 if (image != null) 1272 if (image != null)
1199 image.Dispose(); 1273 image.Dispose();
1200 1274
1201 if (imgstream != null) 1275 if (imgstream != null)
1202 imgstream.Dispose(); 1276 imgstream.Dispose();
1277 }
1278 }
1279 else
1280 {
1281 // Use cached version so we don't have to loose our mind
1282 jpeg = myMapImageJPEG;
1203 } 1283 }
1204 }
1205 else
1206 {
1207 // Use cached version so we don't have to loose our mind
1208 jpeg = myMapImageJPEG;
1209 } 1284 }
1210 1285
1211 reply["str_response_string"] = Convert.ToBase64String(jpeg); 1286 reply["str_response_string"] = Convert.ToBase64String(jpeg);
@@ -1267,22 +1342,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1267 1342
1268 foreach (GridRegion r in regions) 1343 foreach (GridRegion r in regions)
1269 { 1344 {
1270 MapBlockData mapBlock = MapBlockFromGridRegion(r, 0); 1345 MapBlockData mapBlock = new MapBlockData();
1346 MapBlockFromGridRegion(mapBlock, r, 0);
1271 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString()); 1347 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1272 1348
1273 if (texAsset != null) 1349 if (texAsset != null)
1274 { 1350 {
1275 textures.Add(texAsset); 1351 textures.Add(texAsset);
1276 } 1352 }
1277 //else
1278 //{
1279 // // WHAT?!? This doesn't seem right. Commenting (diva)
1280 // texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1281 // if (texAsset != null)
1282 // {
1283 // textures.Add(texAsset);
1284 // }
1285 //}
1286 } 1353 }
1287 1354
1288 foreach (AssetBase asset in textures) 1355 foreach (AssetBase asset in textures)
@@ -1320,17 +1387,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1320 if (consoleScene != null && consoleScene != m_scene) 1387 if (consoleScene != null && consoleScene != m_scene)
1321 return; 1388 return;
1322 1389
1323 if (m_mapImageGenerator == null) 1390 GenerateMaptile();
1324 {
1325 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1326 return;
1327 }
1328
1329 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1330 {
1331 GenerateMaptile(mapbmp);
1332 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1333 }
1334 } 1391 }
1335 1392
1336 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1393 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
@@ -1338,9 +1395,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1338 uint xstart = 0; 1395 uint xstart = 0;
1339 uint ystart = 0; 1396 uint ystart = 0;
1340 1397
1341 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); 1398 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
1342 // m_log.DebugFormat("{0} HandleRemoteMapItemRequest. loc=<{1},{2}>",
1343 // LogHeader, Util.WorldToRegionLoc(xstart), Util.WorldToRegionLoc(ystart));
1344 1399
1345 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots) 1400 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
1346 1401
@@ -1362,8 +1417,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1362 } 1417 }
1363 else 1418 else
1364 { 1419 {
1365 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1420 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1366 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1421 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
1367 { 1422 {
1368 OSDMap responsemapdata = new OSDMap(); 1423 OSDMap responsemapdata = new OSDMap();
1369 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X)); 1424 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X));
@@ -1377,28 +1432,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1377 responsemap["6"] = responsearr; 1432 responsemap["6"] = responsearr;
1378 } 1433 }
1379 1434
1380 // Service 7 (MAP_ITEM_LAND_FOR_SALE) 1435 // Service 7/10 (MAP_ITEM_LAND_FOR_SALE/ADULT)
1381 1436
1382 ILandChannel landChannel = m_scene.LandChannel; 1437 ILandChannel landChannel = m_scene.LandChannel;
1383 List<ILandObject> parcels = landChannel.AllParcels(); 1438 List<ILandObject> parcels = landChannel.AllParcels();
1384 1439
1385 if ((parcels == null) || (parcels.Count == 0)) 1440 if ((parcels != null) && (parcels.Count >= 0))
1386 { 1441 {
1387 OSDMap responsemapdata = new OSDMap(); 1442 OSDArray responsearr = new OSDArray(parcels.Count);
1388 responsemapdata["X"] = OSD.FromInteger((int)(xstart + 1));
1389 responsemapdata["Y"] = OSD.FromInteger((int)(ystart + 1));
1390 responsemapdata["ID"] = OSD.FromUUID(UUID.Zero);
1391 responsemapdata["Name"] = OSD.FromString("");
1392 responsemapdata["Extra"] = OSD.FromInteger(0);
1393 responsemapdata["Extra2"] = OSD.FromInteger(0);
1394 OSDArray responsearr = new OSDArray();
1395 responsearr.Add(responsemapdata);
1396
1397 responsemap["7"] = responsearr;
1398 }
1399 else
1400 {
1401 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount());
1402 foreach (ILandObject parcel_interface in parcels) 1443 foreach (ILandObject parcel_interface in parcels)
1403 { 1444 {
1404 // Play it safe 1445 // Play it safe
@@ -1413,8 +1454,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1413 { 1454 {
1414 Vector3 min = parcel.AABBMin; 1455 Vector3 min = parcel.AABBMin;
1415 Vector3 max = parcel.AABBMax; 1456 Vector3 max = parcel.AABBMax;
1416 float x = (min.X+max.X)/2; 1457 float x = (min.X + max.X) / 2;
1417 float y = (min.Y+max.Y)/2; 1458 float y = (min.Y + max.Y) / 2;
1418 1459
1419 OSDMap responsemapdata = new OSDMap(); 1460 OSDMap responsemapdata = new OSDMap();
1420 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x)); 1461 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x));
@@ -1427,7 +1468,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1427 responsearr.Add(responsemapdata); 1468 responsearr.Add(responsemapdata);
1428 } 1469 }
1429 } 1470 }
1430 responsemap["7"] = responsearr; 1471
1472 if(responsearr.Count > 0)
1473 {
1474 if(m_scene.RegionInfo.RegionSettings.Maturity == 2)
1475 responsemap["10"] = responsearr;
1476 else
1477 responsemap["7"] = responsearr;
1478 }
1431 } 1479 }
1432 1480
1433 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero) 1481 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
@@ -1459,55 +1507,88 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1459 if (m_scene.Heightmap == null) 1507 if (m_scene.Heightmap == null)
1460 return; 1508 return;
1461 1509
1510 if (m_mapImageGenerator == null)
1511 {
1512 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1513 return;
1514 }
1462 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name); 1515 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name);
1463 1516
1464 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile()) 1517 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1465 { 1518 {
1466 // V1 (This Module)
1467 GenerateMaptile(mapbmp); 1519 GenerateMaptile(mapbmp);
1468 1520
1469 // v2/3 (MapImageServiceModule) 1521 if (m_mapImageServiceModule != null)
1470 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp); 1522 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1471 } 1523 }
1472 } 1524 }
1473 1525
1474 private void GenerateMaptile(Bitmap mapbmp) 1526 private void GenerateMaptile(Bitmap mapbmp)
1475 { 1527 {
1476 byte[] data; 1528 bool needRegionSave = false;
1477 1529
1478 try 1530 // remove old assets
1531 UUID lastID = m_scene.RegionInfo.RegionSettings.TerrainImageID;
1532 if (lastID != UUID.Zero)
1479 { 1533 {
1480 data = OpenJPEG.EncodeFromImage(mapbmp, true); 1534 m_scene.AssetService.Delete(lastID.ToString());
1535 m_scene.RegionInfo.RegionSettings.TerrainImageID = UUID.Zero;
1536 needRegionSave = true;
1481 } 1537 }
1482 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 1538
1539 lastID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1540 if (lastID != UUID.Zero)
1483 { 1541 {
1484 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e); 1542 m_scene.AssetService.Delete(lastID.ToString());
1485 return; 1543 m_scene.RegionInfo.RegionSettings.ParcelImageID = UUID.Zero;
1544 needRegionSave = true;
1486 } 1545 }
1487 1546
1488 byte[] overlay = GenerateOverlay(); 1547 // bypass terrain image for large regions
1548 if (m_scene.RegionInfo.RegionSizeX <= Constants.RegionSize &&
1549 m_scene.RegionInfo.RegionSizeY <= Constants.RegionSize
1550 && mapbmp != null)
1551 {
1552 try
1553 {
1554 byte[] data;
1555
1556 data = OpenJPEG.EncodeFromImage(mapbmp, true);
1557
1558 if (data != null && data.Length > 0)
1559 {
1560 UUID terrainImageID = UUID.Random();
1489 1561
1490 UUID terrainImageID = UUID.Random(); 1562 AssetBase asset = new AssetBase(
1491 UUID parcelImageID = UUID.Zero; 1563 terrainImageID,
1564 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(),
1565 (sbyte)AssetType.Texture,
1566 m_scene.RegionInfo.RegionID.ToString());
1567 asset.Data = data;
1568 asset.Description = m_scene.RegionInfo.RegionName;
1569 asset.Temporary = false;
1570 asset.Flags = AssetFlags.Maptile;
1492 1571
1493 AssetBase asset = new AssetBase( 1572 // Store the new one
1494 terrainImageID, 1573 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1495 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(),
1496 (sbyte)AssetType.Texture,
1497 m_scene.RegionInfo.RegionID.ToString());
1498 asset.Data = data;
1499 asset.Description = m_scene.RegionInfo.RegionName;
1500 asset.Temporary = false;
1501 asset.Flags = AssetFlags.Maptile;
1502 1574
1503 // Store the new one 1575 m_scene.AssetService.Store(asset);
1504 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1505
1506 m_scene.AssetService.Store(asset);
1507 1576
1577 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1578 needRegionSave = true;
1579 }
1580 }
1581 catch (Exception e)
1582 {
1583 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e);
1584 }
1585 }
1586
1587 // V2/3 still seem to need this, or we are missing something somewhere
1588 byte[] overlay = GenerateOverlay();
1508 if (overlay != null) 1589 if (overlay != null)
1509 { 1590 {
1510 parcelImageID = UUID.Random(); 1591 UUID parcelImageID = UUID.Random();
1511 1592
1512 AssetBase parcels = new AssetBase( 1593 AssetBase parcels = new AssetBase(
1513 parcelImageID, 1594 parcelImageID,
@@ -1520,20 +1601,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1520 parcels.Flags = AssetFlags.Maptile; 1601 parcels.Flags = AssetFlags.Maptile;
1521 1602
1522 m_scene.AssetService.Store(parcels); 1603 m_scene.AssetService.Store(parcels);
1604
1605 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1606 needRegionSave = true;
1523 } 1607 }
1524 1608
1525 // Switch to the new one 1609 if (needRegionSave)
1526 UUID lastTerrainImageID = m_scene.RegionInfo.RegionSettings.TerrainImageID; 1610 m_scene.RegionInfo.RegionSettings.Save();
1527 UUID lastParcelImageID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1528 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1529 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1530 m_scene.RegionInfo.RegionSettings.Save();
1531
1532 // Delete the old one
1533 // m_log.DebugFormat("[WORLDMAP]: Deleting old map tile {0}", lastTerrainImageID);
1534 m_scene.AssetService.Delete(lastTerrainImageID.ToString());
1535 if (lastParcelImageID != UUID.Zero)
1536 m_scene.AssetService.Delete(lastParcelImageID.ToString());
1537 } 1611 }
1538 1612
1539 private void MakeRootAgent(ScenePresence avatar) 1613 private void MakeRootAgent(ScenePresence avatar)
@@ -1553,6 +1627,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1553 { 1627 {
1554 m_rootAgents.Remove(avatar.UUID); 1628 m_rootAgents.Remove(avatar.UUID);
1555 } 1629 }
1630
1631 lock (m_mapBlockRequestEvent)
1632 {
1633 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1634 m_mapBlockRequests.Remove(avatar.UUID);
1635 }
1556 } 1636 }
1557 1637
1558 public void OnRegionUp(GridRegion otherRegion) 1638 public void OnRegionUp(GridRegion otherRegion)
@@ -1562,46 +1642,67 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1562 1642
1563 lock (m_blacklistedregions) 1643 lock (m_blacklistedregions)
1564 { 1644 {
1565 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1645 if (m_blacklistedregions.Contains(regionhandle))
1566 m_blacklistedregions.Remove(regionhandle); 1646 m_blacklistedregions.Remove(regionhandle);
1567 } 1647 }
1568 1648
1569 lock (m_blacklistedurls) 1649 lock (m_blacklistedurls)
1570 { 1650 {
1571 if (m_blacklistedurls.ContainsKey(httpserver)) 1651 if (m_blacklistedurls.Contains(httpserver))
1572 m_blacklistedurls.Remove(httpserver); 1652 m_blacklistedurls.Remove(httpserver);
1573 } 1653 }
1574 1654
1575 lock (m_cachedRegionMapItemsAddress) 1655 lock (m_cachedRegionMapItemsAddress)
1576 { 1656 {
1577 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 1657 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle,
1578 m_cachedRegionMapItemsAddress.Remove(regionhandle); 1658 httpserver, 5.0 * expireBlackListTime);
1579 } 1659 }
1580 } 1660 }
1581 1661
1582 private Byte[] GenerateOverlay() 1662 private Byte[] GenerateOverlay()
1583 { 1663 {
1664 int landTileSize = LandManagementModule.LandUnit;
1665
1584 // These need to be ints for bitmap generation 1666 // These need to be ints for bitmap generation
1585 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; 1667 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
1586 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1587
1588 int landTileSize = LandManagementModule.LandUnit;
1589 int regionLandTilesX = regionSizeX / landTileSize; 1668 int regionLandTilesX = regionSizeX / landTileSize;
1669
1670 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1590 int regionLandTilesY = regionSizeY / landTileSize; 1671 int regionLandTilesY = regionSizeY / landTileSize;
1591 1672
1592 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY)) 1673 bool landForSale = false;
1674 ILandObject land;
1675
1676 // scan terrain avoiding potencial merges of large bitmaps
1677 //TODO create the sell bitmap at landchannel / landmaster ?
1678 // and auction also, still not suported
1679
1680 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY];
1681 for (int x = 0, xx = 0; x < regionLandTilesX; x++ ,xx += landTileSize)
1593 { 1682 {
1594 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY]; 1683 for (int y = 0, yy = 0; y < regionLandTilesY; y++, yy += landTileSize)
1595 for (int x = 0; x < regionLandTilesX; x++)
1596 { 1684 {
1597 for (int y = 0; y < regionLandTilesY; y++) 1685 land = m_scene.LandChannel.GetLandObject(xx, yy);
1686 if (land != null && (land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1687 {
1688 saleBitmap[x, y] = true;
1689 landForSale = true;
1690 }
1691 else
1598 saleBitmap[x, y] = false; 1692 saleBitmap[x, y] = false;
1599 } 1693 }
1694 }
1600 1695
1601 bool landForSale = false; 1696 if (!landForSale)
1697 {
1698 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1699 return null;
1700 }
1602 1701
1603 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1702 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1604 1703
1704 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY))
1705 {
1605 Color background = Color.FromArgb(0, 0, 0, 0); 1706 Color background = Color.FromArgb(0, 0, 0, 0);
1606 1707
1607 using (Graphics g = Graphics.FromImage(overlay)) 1708 using (Graphics g = Graphics.FromImage(overlay))
@@ -1609,36 +1710,19 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1609 using (SolidBrush transparent = new SolidBrush(background)) 1710 using (SolidBrush transparent = new SolidBrush(background))
1610 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY); 1711 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY);
1611 1712
1612 foreach (ILandObject land in parcels) 1713 // make it a bit transparent
1714 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(192, 249, 223, 9)))
1613 { 1715 {
1614 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags); 1716 for (int x = 0; x < regionLandTilesX; x++)
1615 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1616 { 1717 {
1617 landForSale = true; 1718 for (int y = 0; y < regionLandTilesY; y++)
1618
1619 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1620 }
1621 }
1622
1623 if (!landForSale)
1624 {
1625 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1626 return null;
1627 }
1628
1629 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1630
1631 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
1632 {
1633 for (int x = 0 ; x < regionLandTilesX ; x++)
1634 {
1635 for (int y = 0 ; y < regionLandTilesY ; y++)
1636 { 1719 {
1637 if (saleBitmap[x, y]) 1720 if (saleBitmap[x, y])
1638 g.FillRectangle( 1721 g.FillRectangle(
1639 yellow, x * landTileSize, 1722 yellow,
1640 regionSizeX - landTileSize - (y * landTileSize), 1723 x * landTileSize,
1641 landTileSize, 1724 regionSizeX - landTileSize - (y * landTileSize),
1725 landTileSize,
1642 landTileSize); 1726 landTileSize);
1643 } 1727 }
1644 } 1728 }
@@ -1659,7 +1743,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1659 } 1743 }
1660 } 1744 }
1661 1745
1662 public struct MapRequestState 1746 public class MapRequestState
1663 { 1747 {
1664 public UUID agentID; 1748 public UUID agentID;
1665 public uint flags; 1749 public uint flags;
@@ -1668,4 +1752,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1668 public uint itemtype; 1752 public uint itemtype;
1669 public ulong regionhandle; 1753 public ulong regionhandle;
1670 } 1754 }
1755
1756 public struct MapBlockRequestData
1757 {
1758 public IClientAPI client;
1759 public int minX;
1760 public int minY;
1761 public int maxX;
1762 public int maxY;
1763 public uint flags;
1764 }
1671} 1765}