aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs142
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs463
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs169
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs211
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs260
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs100
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs56
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs168
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs32
15 files changed, 1134 insertions, 555 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 8a3eeaa..6323160 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Region.Framework;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Scenes.Serialization; 42using OpenSim.Region.Framework.Scenes.Serialization;
43using OpenSim.Services.Interfaces;
43 44
44namespace OpenSim.Region.CoreModules.Avatar.Attachments 45namespace OpenSim.Region.CoreModules.Avatar.Attachments
45{ 46{
@@ -75,40 +76,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
75 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 76 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
76 77
77 if (Enabled) 78 if (Enabled)
78 {
79 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 79 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
80 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
81 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
82 }
83 80
84 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 81 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
85 } 82 }
86
87 /// <summary>
88 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
89 /// </summary>
90 /// <param name='localID'></param>
91 /// <param name='itemID'></param>
92 private void HandleScriptStateChange(uint localID, bool started)
93 {
94 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID);
95 if (sog != null && sog.IsAttachment)
96 {
97 if (!started)
98 {
99 // FIXME: This is a convoluted way for working out whether the script state has changed to stop
100 // because it has been manually stopped or because the stop was called in UpdateDetachedObject() below
101 // This needs to be handled in a less tangled way.
102 ScenePresence sp = m_scene.GetScenePresence(sog.AttachedAvatar);
103 if (sp.ControllingClient.IsActive)
104 sog.HasGroupChanged = true;
105 }
106 else
107 {
108 sog.HasGroupChanged = true;
109 }
110 }
111 }
112 83
113 public void RemoveRegion(Scene scene) 84 public void RemoveRegion(Scene scene)
114 { 85 {
@@ -199,6 +170,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
199 170
200// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name); 171// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name);
201 172
173 XmlDocument doc = new XmlDocument();
174 string stateData = String.Empty;
175
176 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
177 if (attServ != null)
178 {
179 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
180 stateData = attServ.Get(sp.UUID.ToString());
181 if (stateData != String.Empty)
182 {
183 try
184 {
185 doc.LoadXml(stateData);
186 }
187 catch { }
188 }
189 }
190
191 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
192
193 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
194 if (nodes.Count > 0)
195 {
196 foreach (XmlNode n in nodes)
197 {
198 XmlElement elem = (XmlElement)n;
199 string itemID = elem.GetAttribute("ItemID");
200 string xml = elem.InnerXml;
201
202 itemData[new UUID(itemID)] = xml;
203 }
204 }
205
206
202 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 207 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
203 foreach (AvatarAttachment attach in attachments) 208 foreach (AvatarAttachment attach in attachments)
204 { 209 {
@@ -218,12 +223,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
218 223
219 try 224 try
220 { 225 {
226 string xmlData;
227 XmlDocument d = null;
228 UUID asset;
229 if (itemData.TryGetValue(attach.ItemID, out xmlData))
230 {
231 d = new XmlDocument();
232 d.LoadXml(xmlData);
233 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
234 }
235
221 // If we're an NPC then skip all the item checks and manipulations since we don't have an 236 // If we're an NPC then skip all the item checks and manipulations since we don't have an
222 // inventory right now. 237 // inventory right now.
223 if (sp.PresenceType == PresenceType.Npc) 238 if (sp.PresenceType == PresenceType.Npc)
224 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p); 239 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null);
225 else 240 else
226 RezSingleAttachmentFromInventory(sp, attach.ItemID, p); 241 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, d);
227 } 242 }
228 catch (Exception e) 243 catch (Exception e)
229 { 244 {
@@ -268,13 +283,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
268 283
269 sp.ClearAttachments(); 284 sp.ClearAttachments();
270 } 285 }
271 286
272 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
273 { 288 {
274 if (!Enabled) 289 if (!Enabled)
275 return false; 290 return false;
276 291
277 if (AttachObjectInternal(sp, group, attachmentPt, silent, temp)) 292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp))
278 { 293 {
279 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); 294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
280 return true; 295 return true;
@@ -283,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
283 return false; 298 return false;
284 } 299 }
285 300
286 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) 301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
287 { 302 {
288 lock (sp.AttachmentsSyncLock) 303 lock (sp.AttachmentsSyncLock)
289 { 304 {
@@ -338,6 +353,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
338 attachPos = Vector3.Zero; 353 attachPos = Vector3.Zero;
339 } 354 }
340 355
356 if (useAttachData)
357 {
358 group.RootPart.RotationOffset = group.RootPart.AttachRotation;
359 attachPos = group.RootPart.AttachOffset;
360 if (attachmentPt == 0)
361 {
362 attachmentPt = group.RootPart.AttachPoint;
363 if (attachmentPt == 0)
364 {
365 attachmentPt = (uint)AttachmentPoint.LeftHand;
366 attachPos = Vector3.Zero;
367 }
368 }
369 else if (group.RootPart.AttachPoint != attachmentPt)
370 {
371 attachPos = Vector3.Zero;
372 }
373 }
341 group.AttachmentPoint = attachmentPt; 374 group.AttachmentPoint = attachmentPt;
342 group.AbsolutePosition = attachPos; 375 group.AbsolutePosition = attachPos;
343 376
@@ -378,7 +411,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
378 } 411 }
379 } 412 }
380 413
381 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 414 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
415 {
416 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
417 }
418
419 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
382 { 420 {
383 if (!Enabled) 421 if (!Enabled)
384 return null; 422 return null;
@@ -417,7 +455,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
417 return null; 455 return null;
418 } 456 }
419 457
420 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); 458 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
421 } 459 }
422 460
423 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 461 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -491,7 +529,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
491 so.AttachedAvatar = UUID.Zero; 529 so.AttachedAvatar = UUID.Zero;
492 rootPart.SetParentLocalId(0); 530 rootPart.SetParentLocalId(0);
493 so.ClearPartAttachmentData(); 531 so.ClearPartAttachmentData();
494 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); 532 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive,false);
495 so.HasGroupChanged = true; 533 so.HasGroupChanged = true;
496 rootPart.Rezzed = DateTime.Now; 534 rootPart.Rezzed = DateTime.Now;
497 rootPart.RemFlag(PrimFlags.TemporaryOnRez); 535 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
@@ -803,8 +841,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
803 UpdateDetachedObject(sp, so); 841 UpdateDetachedObject(sp, so);
804 } 842 }
805 843
806 private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 844 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
807 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt) 845 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
808 { 846 {
809 if (m_invAccessModule == null) 847 if (m_invAccessModule == null)
810 return null; 848 return null;
@@ -842,7 +880,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
842 // This will throw if the attachment fails 880 // This will throw if the attachment fails
843 try 881 try
844 { 882 {
845 AttachObjectInternal(sp, objatt, attachmentPt, false, false); 883 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false);
846 } 884 }
847 catch (Exception e) 885 catch (Exception e)
848 { 886 {
@@ -855,10 +893,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
855 m_scene.DeleteSceneObject(objatt, false); 893 m_scene.DeleteSceneObject(objatt, false);
856 return null; 894 return null;
857 } 895 }
858 896
859 if (tainted) 897 if (tainted)
860 objatt.HasGroupChanged = true; 898 objatt.HasGroupChanged = true;
861 899
900 if (doc != null)
901 {
902 objatt.LoadScriptState(doc);
903 objatt.ResetOwnerChangeFlag();
904 }
905
862 // Fire after attach, so we don't get messy perms dialogs 906 // Fire after attach, so we don't get messy perms dialogs
863 // 4 == AttachedRez 907 // 4 == AttachedRez
864 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); 908 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
@@ -876,7 +920,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
876 itemID, sp.Name, attachmentPt); 920 itemID, sp.Name, attachmentPt);
877 } 921 }
878 } 922 }
879 923
880 return null; 924 return null;
881 } 925 }
882 926
@@ -999,7 +1043,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
999 AttachmentPt &= 0x7f; 1043 AttachmentPt &= 0x7f;
1000 1044
1001 // Calls attach with a Zero position 1045 // Calls attach with a Zero position
1002 AttachObject(sp, part.ParentGroup, AttachmentPt, false, false); 1046 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false))
1047 {
1048// m_log.Debug(
1049// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
1050// + ", AttachmentPoint: " + AttachmentPt);
1051
1052 // Save avatar attachment information
1053 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
1054 }
1003 } 1055 }
1004 catch (Exception e) 1056 catch (Exception e)
1005 { 1057 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ee01c7..4e9d3f9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -197,7 +197,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 198
199 m_numberOfAttachEventsFired = 0; 199 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
201 201
202 // Check status on scene presence 202 // Check status on scene presence
203 Assert.That(sp.HasAttachments(), Is.True); 203 Assert.That(sp.HasAttachments(), Is.True);
@@ -254,7 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
254 sp2.AbsolutePosition = new Vector3(0, 0, 0); 254 sp2.AbsolutePosition = new Vector3(0, 0, 0);
255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
256 256
257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
258 258
259 Assert.That(sp.HasAttachments(), Is.False); 259 Assert.That(sp.HasAttachments(), Is.False);
260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -438,7 +438,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
438 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 438 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
439 439
440 SceneObjectGroup rezzedSo 440 SceneObjectGroup rezzedSo
441 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 441 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
442 442
443 // Wait for chat to signal rezzed script has been started. 443 // Wait for chat to signal rezzed script has been started.
444 m_chatEvent.WaitOne(60000); 444 m_chatEvent.WaitOne(60000);
@@ -457,7 +457,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
457 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 457 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
458 458
459 // Re-rez the attachment to check script running state 459 // Re-rez the attachment to check script running state
460 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 460 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
461 461
462 // Wait for chat to signal rezzed script has been started. 462 // Wait for chat to signal rezzed script has been started.
463 m_chatEvent.WaitOne(60000); 463 m_chatEvent.WaitOne(60000);
@@ -663,4 +663,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
664 } 664 }
665 } 665 }
666} \ No newline at end of file 666}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 00d1fd8..864f33e 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -140,9 +140,24 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
140 /// <param name="sp"></param> 140 /// <param name="sp"></param>
141 /// <param name="texture"></param> 141 /// <param name="texture"></param>
142 /// <param name="visualParam"></param> 142 /// <param name="visualParam"></param>
143 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) 143 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems)
144 { 144 {
145 SetAppearance(sp, appearance.Texture, appearance.VisualParams); 145 SetAppearance(sp, appearance.Texture, appearance.VisualParams, cacheItems);
146 }
147
148
149 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
150 {
151 float oldoff = sp.Appearance.AvatarFeetOffset;
152 Vector3 oldbox = sp.Appearance.AvatarBoxSize;
153
154 SetAppearance(sp, textureEntry, visualParams, cacheItems);
155 sp.Appearance.SetSize(avSize);
156
157 float off = sp.Appearance.AvatarFeetOffset;
158 Vector3 box = sp.Appearance.AvatarBoxSize;
159 if (oldoff != off || oldbox != box)
160 ((ScenePresence)sp).SetSize(box, off);
146 } 161 }
147 162
148 /// <summary> 163 /// <summary>
@@ -151,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
151 /// <param name="sp"></param> 166 /// <param name="sp"></param>
152 /// <param name="texture"></param> 167 /// <param name="texture"></param>
153 /// <param name="visualParam"></param> 168 /// <param name="visualParam"></param>
154 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) 169 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems)
155 { 170 {
156// m_log.DebugFormat( 171// m_log.DebugFormat(
157// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", 172// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
@@ -174,18 +189,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
174 // m_log.DebugFormat( 189 // m_log.DebugFormat(
175 // "[AVFACTORY]: Setting visual params for {0} to {1}", 190 // "[AVFACTORY]: Setting visual params for {0} to {1}",
176 // client.Name, string.Join(", ", visualParamsStrings)); 191 // client.Name, string.Join(", ", visualParamsStrings));
177 192/*
178 float oldHeight = sp.Appearance.AvatarHeight; 193 float oldHeight = sp.Appearance.AvatarHeight;
179 changed = sp.Appearance.SetVisualParams(visualParams); 194 changed = sp.Appearance.SetVisualParams(visualParams);
180 195
181 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) 196 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
182 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); 197 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
183 } 198 */
199// float oldoff = sp.Appearance.AvatarFeetOffset;
200// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
201 changed = sp.Appearance.SetVisualParams(visualParams);
202// float off = sp.Appearance.AvatarFeetOffset;
203// Vector3 box = sp.Appearance.AvatarBoxSize;
204// if(oldoff != off || oldbox != box)
205// ((ScenePresence)sp).SetSize(box,off);
184 206
207 }
208
185 // Process the baked texture array 209 // Process the baked texture array
186 if (textureEntry != null) 210 if (textureEntry != null)
187 { 211 {
188// m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); 212 m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);
189 213
190// WriteBakedTexturesReport(sp, m_log.DebugFormat); 214// WriteBakedTexturesReport(sp, m_log.DebugFormat);
191 215
@@ -254,6 +278,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
254 return GetBakedTextureFaces(sp); 278 return GetBakedTextureFaces(sp);
255 } 279 }
256 280
281 public WearableCacheItem[] GetCachedItems(UUID agentId)
282 {
283 ScenePresence sp = m_scene.GetScenePresence(agentId);
284 WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
285 //foreach (WearableCacheItem item in items)
286 //{
287
288 //}
289 return items;
290 }
291
257 public bool SaveBakedTextures(UUID agentId) 292 public bool SaveBakedTextures(UUID agentId)
258 { 293 {
259 ScenePresence sp = m_scene.GetScenePresence(agentId); 294 ScenePresence sp = m_scene.GetScenePresence(agentId);
@@ -340,6 +375,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
340 public bool ValidateBakedTextureCache(IScenePresence sp) 375 public bool ValidateBakedTextureCache(IScenePresence sp)
341 { 376 {
342 bool defonly = true; // are we only using default textures 377 bool defonly = true; // are we only using default textures
378 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
379 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
380 WearableCacheItem[] wearableCache = null;
381
382 // Cache wearable data for teleport.
383 // Only makes sense if there's a bake module and a cache module
384 if (bakedModule != null && cache != null)
385 {
386 try
387 {
388 wearableCache = bakedModule.Get(sp.UUID);
389 }
390 catch (Exception)
391 {
392
393 }
394 if (wearableCache != null)
395 {
396 for (int i = 0; i < wearableCache.Length; i++)
397 {
398 cache.Cache(wearableCache[i].TextureAsset);
399 }
400 }
401 }
402 /*
403 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
404 if (invService.GetRootFolder(userID) != null)
405 {
406 WearableCacheItem[] wearableCache = null;
407 if (bakedModule != null)
408 {
409 try
410 {
411 wearableCache = bakedModule.Get(userID);
412 appearance.WearableCacheItems = wearableCache;
413 appearance.WearableCacheItemsDirty = false;
414 foreach (WearableCacheItem item in wearableCache)
415 {
416 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID;
417 }
418 }
419 catch (Exception)
420 {
421
422 }
423 }
424 */
343 425
344 // Process the texture entry 426 // Process the texture entry
345 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 427 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
@@ -347,9 +429,32 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
347 int idx = AvatarAppearance.BAKE_INDICES[i]; 429 int idx = AvatarAppearance.BAKE_INDICES[i];
348 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; 430 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
349 431
350 // if there is no texture entry, skip it 432 // No face, so lets check our baked service cache, teleport or login.
351 if (face == null) 433 if (face == null)
352 continue; 434 {
435 if (wearableCache != null)
436 {
437 // If we find the an appearance item, set it as the textureentry and the face
438 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache);
439 if (searchitem != null)
440 {
441 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
442 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID;
443 face = sp.Appearance.Texture.FaceTextures[idx];
444 }
445 else
446 {
447 // if there is no texture entry and no baked cache, skip it
448 continue;
449 }
450 }
451 else
452 {
453 //No texture entry face and no cache. Skip this face.
454 continue;
455 }
456 }
457
353 458
354// m_log.DebugFormat( 459// m_log.DebugFormat(
355// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", 460// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
@@ -364,8 +469,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
364 469
365 defonly = false; // found a non-default texture reference 470 defonly = false; // found a non-default texture reference
366 471
367 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) 472 if (cache != null)
368 return false; 473 {
474 if (!cache.Check(face.TextureID.ToString()))
475 return false;
476 }
477 else
478 {
479 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
480 return false;
481 }
369 } 482 }
370 483
371// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 484// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID);
@@ -377,6 +490,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 490 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
378 { 491 {
379 int texturesRebaked = 0; 492 int texturesRebaked = 0;
493 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
380 494
381 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 495 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
382 { 496 {
@@ -400,21 +514,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
400 514
401 if (missingTexturesOnly) 515 if (missingTexturesOnly)
402 { 516 {
403 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 517 if (cache != null)
404 { 518 {
405 continue; 519 if (cache.Check(face.TextureID.ToString()))
520 continue;
521 else
522 {
523 m_log.DebugFormat(
524 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
525 face.TextureID, idx, sp.Name);
526 }
406 } 527 }
407 else 528 else
408 { 529 {
409 // On inter-simulator teleports, this occurs if baked textures are not being stored by the 530 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null)
410 // grid asset service (which means that they are not available to the new region and so have 531 {
411 // to be re-requested from the client). 532 continue;
412 // 533 }
413 // The only available core OpenSimulator behaviour right now 534
414 // is not to store these textures, temporarily or otherwise. 535 else
415 m_log.DebugFormat( 536 {
416 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 537 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
417 face.TextureID, idx, sp.Name); 538 // grid asset service (which means that they are not available to the new region and so have
539 // to be re-requested from the client).
540 //
541 // The only available core OpenSimulator behaviour right now
542 // is not to store these textures, temporarily or otherwise.
543 m_log.DebugFormat(
544 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
545 face.TextureID, idx, sp.Name);
546 }
418 } 547 }
419 } 548 }
420 else 549 else
@@ -548,26 +677,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
548 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) 677 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
549 { 678 {
550 IInventoryService invService = m_scene.InventoryService; 679 IInventoryService invService = m_scene.InventoryService;
551 680 bool resetwearable = false;
552 if (invService.GetRootFolder(userID) != null) 681 if (invService.GetRootFolder(userID) != null)
553 { 682 {
554 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 683 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
555 { 684 {
556 for (int j = 0; j < appearance.Wearables[i].Count; j++) 685 for (int j = 0; j < appearance.Wearables[i].Count; j++)
557 { 686 {
687 // Check if the default wearables are not set
558 if (appearance.Wearables[i][j].ItemID == UUID.Zero) 688 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
689 {
690 switch ((WearableType) i)
691 {
692 case WearableType.Eyes:
693 case WearableType.Hair:
694 case WearableType.Shape:
695 case WearableType.Skin:
696 //case WearableType.Underpants:
697 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
698 resetwearable = true;
699 m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values.");
700 resetwearable = true;
701 break;
702
703 }
559 continue; 704 continue;
705 }
560 706
561 // Ignore ruth's assets 707 // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1
562 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 708 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
709 {
710 switch ((WearableType)i)
711 {
712 case WearableType.Eyes:
713 case WearableType.Hair:
714 case WearableType.Shape:
715 case WearableType.Skin:
716 //case WearableType.Underpants:
717 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
718
719 m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
720 resetwearable = true;
721 break;
722
723 }
563 continue; 724 continue;
564 725 }
726
565 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 727 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
566 baseItem = invService.GetItem(baseItem); 728 baseItem = invService.GetItem(baseItem);
567 729
568 if (baseItem != null) 730 if (baseItem != null)
569 { 731 {
570 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); 732 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
733 int unmodifiedWearableIndexForClosure = i;
734 m_scene.AssetService.Get(baseItem.AssetID.ToString(), this,
735 delegate(string x, object y, AssetBase z)
736 {
737 if (z == null)
738 {
739 TryAndRepairBrokenWearable(
740 (WearableType)unmodifiedWearableIndexForClosure, invService,
741 userID, appearance);
742 }
743 });
571 } 744 }
572 else 745 else
573 { 746 {
@@ -575,17 +748,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
575 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", 748 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
576 appearance.Wearables[i][j].ItemID, (WearableType)i); 749 appearance.Wearables[i][j].ItemID, (WearableType)i);
577 750
578 appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); 751 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
752 resetwearable = true;
753
579 } 754 }
580 } 755 }
581 } 756 }
757
758 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
759 if (appearance.Wearables[(int) WearableType.Eyes] == null)
760 {
761 m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
762
763 TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
764 resetwearable = true;
765 }
766 else
767 {
768 if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero)
769 {
770 m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}",
771 appearance.Wearables[(int) WearableType.Eyes][0].ItemID,
772 appearance.Wearables[(int) WearableType.Eyes][0].AssetID);
773 TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
774 resetwearable = true;
775
776 }
777
778 }
779 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
780 if (appearance.Wearables[(int)WearableType.Shape] == null)
781 {
782 m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape));
783
784 TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
785 resetwearable = true;
786 }
787 else
788 {
789 if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero)
790 {
791 m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}",
792 appearance.Wearables[(int)WearableType.Shape][0].ItemID,
793 appearance.Wearables[(int)WearableType.Shape][0].AssetID);
794 TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
795 resetwearable = true;
796
797 }
798
799 }
800 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
801 if (appearance.Wearables[(int)WearableType.Hair] == null)
802 {
803 m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair));
804
805 TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
806 resetwearable = true;
807 }
808 else
809 {
810 if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero)
811 {
812 m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}",
813 appearance.Wearables[(int)WearableType.Hair][0].ItemID,
814 appearance.Wearables[(int)WearableType.Hair][0].AssetID);
815 TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
816 resetwearable = true;
817
818 }
819
820 }
821 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
822 if (appearance.Wearables[(int)WearableType.Skin] == null)
823 {
824 m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin));
825
826 TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
827 resetwearable = true;
828 }
829 else
830 {
831 if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero)
832 {
833 m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}",
834 appearance.Wearables[(int)WearableType.Skin][0].ItemID,
835 appearance.Wearables[(int)WearableType.Skin][0].AssetID);
836 TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
837 resetwearable = true;
838
839 }
840
841 }
842 if (resetwearable)
843 {
844 ScenePresence presence = null;
845 if (m_scene.TryGetScenePresence(userID, out presence))
846 {
847 presence.ControllingClient.SendWearables(presence.Appearance.Wearables,
848 presence.Appearance.Serial++);
849 }
850 }
851
582 } 852 }
583 else 853 else
584 { 854 {
585 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); 855 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
586 } 856 }
587 } 857 }
858 private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance)
859 {
860 UUID defaultwearable = GetDefaultItem(type);
861 if (defaultwearable != UUID.Zero)
862 {
863 UUID newInvItem = UUID.Random();
864 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
865 {
866 AssetID =
867 defaultwearable,
868 AssetType
869 =
870 (int)
871 AssetType
872 .Bodypart,
873 CreatorId
874 =
875 userID
876 .ToString
877 (),
878 //InvType = (int)InventoryType.Wearable,
879
880 Description
881 =
882 "Failed Wearable Replacement",
883 Folder =
884 invService
885 .GetFolderForType
886 (userID,
887 AssetType
888 .Bodypart)
889 .ID,
890 Flags = (uint) type,
891 Name = Enum.GetName(typeof (WearableType), type),
892 BasePermissions = (uint) PermissionMask.Copy,
893 CurrentPermissions = (uint) PermissionMask.Copy,
894 EveryOnePermissions = (uint) PermissionMask.Copy,
895 GroupPermissions = (uint) PermissionMask.Copy,
896 NextPermissions = (uint) PermissionMask.Copy
897 };
898 invService.AddItem(itembase);
899 UUID LinkInvItem = UUID.Random();
900 itembase = new InventoryItemBase(LinkInvItem, userID)
901 {
902 AssetID =
903 newInvItem,
904 AssetType
905 =
906 (int)
907 AssetType
908 .Link,
909 CreatorId
910 =
911 userID
912 .ToString
913 (),
914 InvType = (int) InventoryType.Wearable,
915
916 Description
917 =
918 "Failed Wearable Replacement",
919 Folder =
920 invService
921 .GetFolderForType
922 (userID,
923 AssetType
924 .CurrentOutfitFolder)
925 .ID,
926 Flags = (uint) type,
927 Name = Enum.GetName(typeof (WearableType), type),
928 BasePermissions = (uint) PermissionMask.Copy,
929 CurrentPermissions = (uint) PermissionMask.Copy,
930 EveryOnePermissions = (uint) PermissionMask.Copy,
931 GroupPermissions = (uint) PermissionMask.Copy,
932 NextPermissions = (uint) PermissionMask.Copy
933 };
934 invService.AddItem(itembase);
935 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
936 ScenePresence presence = null;
937 if (m_scene.TryGetScenePresence(userID, out presence))
938 {
939 m_scene.SendInventoryUpdate(presence.ControllingClient,
940 invService.GetFolderForType(userID,
941 AssetType
942 .CurrentOutfitFolder),
943 false, true);
944 }
945 }
946 }
947 private UUID GetDefaultItem(WearableType wearable)
948 {
949 // These are ruth
950 UUID ret = UUID.Zero;
951 switch (wearable)
952 {
953 case WearableType.Eyes:
954 ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7");
955 break;
956 case WearableType.Hair:
957 ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66");
958 break;
959 case WearableType.Pants:
960 ret = new UUID("00000000-38f9-1111-024e-222222111120");
961 break;
962 case WearableType.Shape:
963 ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
964 break;
965 case WearableType.Shirt:
966 ret = new UUID("00000000-38f9-1111-024e-222222111110");
967 break;
968 case WearableType.Skin:
969 ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb");
970 break;
971 case WearableType.Undershirt:
972 ret = new UUID("16499ebb-3208-ec27-2def-481881728f47");
973 break;
974 case WearableType.Underpants:
975 ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d");
976 break;
977 }
588 978
979 return ret;
980 }
589 #endregion 981 #endregion
590 982
591 #region Client Event Handlers 983 #region Client Event Handlers
@@ -595,12 +987,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
595 /// <param name="client"></param> 987 /// <param name="client"></param>
596 private void Client_OnRequestWearables(IClientAPI client) 988 private void Client_OnRequestWearables(IClientAPI client)
597 { 989 {
598 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); 990 Util.FireAndForget(delegate(object x)
599 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 991 {
600 if (sp != null) 992 Thread.Sleep(4000);
601 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); 993
602 else 994 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId);
603 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); 995 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
996 if (sp != null)
997 client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
998 else
999 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
1000 });
604 } 1001 }
605 1002
606 /// <summary> 1003 /// <summary>
@@ -609,12 +1006,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
609 /// <param name="client"></param> 1006 /// <param name="client"></param>
610 /// <param name="texture"></param> 1007 /// <param name="texture"></param>
611 /// <param name="visualParam"></param> 1008 /// <param name="visualParam"></param>
612 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) 1009 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
613 { 1010 {
614 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); 1011 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
615 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 1012 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
616 if (sp != null) 1013 if (sp != null)
617 SetAppearance(sp, textureEntry, visualParams); 1014 SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems);
618 else 1015 else
619 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); 1016 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
620 } 1017 }
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 1830d41..f090e15 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
61 for (byte i = 0; i < visualParams.Length; i++) 61 for (byte i = 0; i < visualParams.Length; i++)
62 visualParams[i] = i; 62 visualParams[i] = i;
63 63
64 afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); 64 afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams, new WearableCacheItem[0]);
65 65
66 // TODO: Check baked texture 66 // TODO: Check baked texture
67 Assert.AreEqual(visualParams, sp.Appearance.VisualParams); 67 Assert.AreEqual(visualParams, sp.Appearance.VisualParams);
@@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
102 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 102 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
103 eyesFace.TextureID = eyesTextureId; 103 eyesFace.TextureID = eyesTextureId;
104 104
105 afm.SetAppearance(sp, bakedTextureEntry, visualParams); 105 afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
106 afm.SaveBakedTextures(userId); 106 afm.SaveBakedTextures(userId);
107// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 107// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
108 108
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 6d62ff0..4c3f1cc 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
51 private int m_shoutdistance = 100; 51 private int m_shoutdistance = 100;
52 private int m_whisperdistance = 10; 52 private int m_whisperdistance = 10;
53 private List<Scene> m_scenes = new List<Scene>(); 53 private List<Scene> m_scenes = new List<Scene>();
54 54 private List<string> FreezeCache = new List<string>();
55 private string m_adminPrefix = "";
55 internal object m_syncy = new object(); 56 internal object m_syncy = new object();
56 57
57 internal IConfig m_config; 58 internal IConfig m_config;
@@ -78,6 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
78 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 79 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
79 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 80 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
80 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 81 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
82 m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", "");
81 } 83 }
82 84
83 public virtual void AddRegion(Scene scene) 85 public virtual void AddRegion(Scene scene)
@@ -173,7 +175,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
173 return; 175 return;
174 } 176 }
175 177
176 DeliverChatToAvatars(ChatSourceType.Agent, c); 178 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
179 {
180 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
181 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
182 }
183 else
184 {
185 DeliverChatToAvatars(ChatSourceType.Agent, c);
186 }
177 } 187 }
178 188
179 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 189 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -187,11 +197,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
187 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 197 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
188 { 198 {
189 string fromName = c.From; 199 string fromName = c.From;
200 string fromNamePrefix = "";
190 UUID fromID = UUID.Zero; 201 UUID fromID = UUID.Zero;
191 UUID ownerID = UUID.Zero; 202 UUID ownerID = UUID.Zero;
192 UUID targetID = c.TargetUUID;
193 string message = c.Message; 203 string message = c.Message;
194 IScene scene = c.Scene; 204 IScene scene = c.Scene;
205 UUID destination = c.Destination;
195 Vector3 fromPos = c.Position; 206 Vector3 fromPos = c.Position;
196 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, 207 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
197 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); 208 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
@@ -211,6 +222,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
211 fromPos = avatar.AbsolutePosition; 222 fromPos = avatar.AbsolutePosition;
212 fromName = avatar.Name; 223 fromName = avatar.Name;
213 fromID = c.Sender.AgentId; 224 fromID = c.Sender.AgentId;
225 if (avatar.GodLevel >= 200)
226 {
227 fromNamePrefix = m_adminPrefix;
228 }
229 destination = UUID.Zero; // Avatars cant "SayTo"
214 ownerID = c.Sender.AgentId; 230 ownerID = c.Sender.AgentId;
215 231
216 break; 232 break;
@@ -229,40 +245,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
229 message = message.Substring(0, 1000); 245 message = message.Substring(0, 1000);
230 246
231// m_log.DebugFormat( 247// m_log.DebugFormat(
232// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 248// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
233// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 249// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
234 250
235 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 251 HashSet<UUID> receiverIDs = new HashSet<UUID>();
236 252
237 foreach (Scene s in m_scenes) 253 foreach (Scene s in m_scenes)
238 { 254 {
239 if (targetID == UUID.Zero) 255 // This should use ForEachClient, but clients don't have a position.
240 { 256 // If camera is moved into client, then camera position can be used
241 // This should use ForEachClient, but clients don't have a position. 257 // MT: No, it can't, as chat is heard from the avatar position, not
242 // If camera is moved into client, then camera position can be used 258 // the camera position.
243 s.ForEachRootScenePresence( 259 s.ForEachRootScenePresence(
244 delegate(ScenePresence presence) 260 delegate(ScenePresence presence)
261 {
262 if (destination != UUID.Zero && presence.UUID != destination)
263 return;
264 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
265 if (Presencecheck != null)
245 { 266 {
246 if (TrySendChatMessage( 267 // This will pass all chat from objects. Not
247 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 268 // perfect, but it will do. For now. Better
248 receiverIDs.Add(presence.UUID); 269 // than the prior behavior of muting all
270 // objects on a parcel with access restrictions
271 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
272 {
273 if (destination != UUID.Zero)
274 {
275 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
276 receiverIDs.Add(presence.UUID);
277 }
278 else
279 {
280 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
281 receiverIDs.Add(presence.UUID);
282 }
283 }
249 } 284 }
250 );
251 }
252 else
253 {
254 // This is a send to a specific client eg from llRegionSayTo
255 // no need to check distance etc, jand send is as say
256 ScenePresence presence = s.GetScenePresence(targetID);
257 if (presence != null && !presence.IsChildAgent)
258 {
259 if (TrySendChatMessage(
260 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
261 receiverIDs.Add(presence.UUID);
262 } 285 }
263 } 286 );
264 } 287 }
265 288
266 (scene as Scene).EventManager.TriggerOnChatToClients( 289 (scene as Scene).EventManager.TriggerOnChatToClients(
267 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 290 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
268 } 291 }
@@ -302,28 +325,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
302 } 325 }
303 326
304 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 327 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
305
306 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 328 HashSet<UUID> receiverIDs = new HashSet<UUID>();
307 329
308 ((Scene)c.Scene).ForEachRootClient( 330 if (c.Scene != null)
309 delegate(IClientAPI client) 331 {
310 { 332 ((Scene)c.Scene).ForEachRootClient
311 // don't forward SayOwner chat from objects to 333 (
312 // non-owner agents 334 delegate(IClientAPI client)
313 if ((c.Type == ChatTypeEnum.Owner) && 335 {
314 (null != c.SenderObject) && 336 // don't forward SayOwner chat from objects to
315 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 337 // non-owner agents
316 return; 338 if ((c.Type == ChatTypeEnum.Owner) &&
317 339 (null != c.SenderObject) &&
318 client.SendChatMessage( 340 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
319 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, 341 return;
320 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 342
321 343 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
322 receiverIDs.Add(client.AgentId); 344 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
323 }); 345 receiverIDs.Add(client.AgentId);
324 346 }
325 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 347 );
326 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 348 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
349 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
350 }
327 } 351 }
328 352
329 /// <summary> 353 /// <summary>
@@ -348,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
348 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
349 string message, ChatSourceType src, bool ignoreDistance) 373 string message, ChatSourceType src, bool ignoreDistance)
350 { 374 {
351 // don't send stuff to child agents 375 // don't send chat to child agents
352 if (presence.IsChildAgent) return false; 376 if (presence.IsChildAgent) return false;
353 377
354 Vector3 fromRegionPos = fromPos + regionPos; 378 Vector3 fromRegionPos = fromPos + regionPos;
@@ -357,15 +381,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
357 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); 381 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
358 382
359 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 383 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
360 384
361 if (!ignoreDistance) 385 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
386 type == ChatTypeEnum.Say && dis > m_saydistance ||
387 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
362 { 388 {
363 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || 389 return false;
364 type == ChatTypeEnum.Say && dis > m_saydistance ||
365 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
366 {
367 return false;
368 }
369 } 390 }
370 391
371 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
@@ -375,5 +396,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
375 396
376 return true; 397 return true;
377 } 398 }
399
400 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
401 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
402 {
403 System.Threading.Timer Timer;
404 if (flags == 0)
405 {
406 FreezeCache.Add(target.ToString());
407 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
408 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
409 Timers.Add(target, Timer);
410 }
411 else
412 {
413 FreezeCache.Remove(target.ToString());
414 Timers.TryGetValue(target, out Timer);
415 Timers.Remove(target);
416 Timer.Dispose();
417 }
418 }
419
420 private void OnEndParcelFrozen(object avatar)
421 {
422 UUID target = (UUID)avatar;
423 FreezeCache.Remove(target.ToString());
424 System.Threading.Timer Timer;
425 Timers.TryGetValue(target, out Timer);
426 Timers.Remove(target);
427 Timer.Dispose();
428 }
378 } 429 }
379} \ No newline at end of file 430}
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index d26907b..0e7ab7e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -260,4 +260,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
260 return result; 260 return result;
261 } 261 }
262 } 262 }
263} \ No newline at end of file 263}
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 5a7446f..9fa9be1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -32,6 +32,24 @@ using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35using System;
36using System.Reflection;
37using System.Collections;
38using System.Collections.Specialized;
39using System.Reflection;
40using System.IO;
41using System.Web;
42using System.Xml;
43using log4net;
44using Mono.Addins;
45using OpenMetaverse.Messages.Linden;
46using OpenMetaverse.StructuredData;
47using OpenSim.Framework.Capabilities;
48using OpenSim.Framework.Servers;
49using OpenSim.Framework.Servers.HttpServer;
50using Caps = OpenSim.Framework.Capabilities.Caps;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap;
35 53
36using Mono.Addins; 54using Mono.Addins;
37 55
@@ -40,11 +58,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")] 58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")]
41 public class GodsModule : INonSharedRegionModule, IGodsModule 59 public class GodsModule : INonSharedRegionModule, IGodsModule
42 { 60 {
61 private static readonly ILog m_log =
62 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
63
43 /// <summary>Special UUID for actions that apply to all agents</summary> 64 /// <summary>Special UUID for actions that apply to all agents</summary>
44 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); 65 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
45 66
46 protected Scene m_scene; 67 protected Scene m_scene;
47 protected IDialogModule m_dialogModule; 68 protected IDialogModule m_dialogModule;
69
70 protected Dictionary<UUID, string> m_capsDict =
71 new Dictionary<UUID, string>();
72
48 protected IDialogModule DialogModule 73 protected IDialogModule DialogModule
49 { 74 {
50 get 75 get
@@ -65,6 +90,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
65 m_scene = scene; 90 m_scene = scene;
66 m_scene.RegisterModuleInterface<IGodsModule>(this); 91 m_scene.RegisterModuleInterface<IGodsModule>(this);
67 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 92 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
93 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
94 m_scene.EventManager.OnClientClosed += OnClientClosed;
95 scene.EventManager.OnIncomingInstantMessage +=
96 OnIncomingInstantMessage;
68 } 97 }
69 98
70 public void RemoveRegion(Scene scene) 99 public void RemoveRegion(Scene scene)
@@ -98,6 +127,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
98 client.OnRequestGodlikePowers -= RequestGodlikePowers; 127 client.OnRequestGodlikePowers -= RequestGodlikePowers;
99 } 128 }
100 129
130 private void OnClientClosed(UUID agentID, Scene scene)
131 {
132 m_capsDict.Remove(agentID);
133 }
134
135 private void OnRegisterCaps(UUID agentID, Caps caps)
136 {
137 string uri = "/CAPS/" + UUID.Random();
138 m_capsDict[agentID] = uri;
139
140 caps.RegisterHandler("UntrustedSimulatorMessage",
141 new RestStreamHandler("POST", uri,
142 HandleUntrustedSimulatorMessage));
143 }
144
145 private string HandleUntrustedSimulatorMessage(string request,
146 string path, string param, IOSHttpRequest httpRequest,
147 IOSHttpResponse httpResponse)
148 {
149 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
150
151 string message = osd["message"].AsString();
152
153 if (message == "GodKickUser")
154 {
155 OSDMap body = (OSDMap)osd["body"];
156 OSDArray userInfo = (OSDArray)body["UserInfo"];
157 OSDMap userData = (OSDMap)userInfo[0];
158
159 UUID agentID = userData["AgentID"].AsUUID();
160 UUID godID = userData["GodID"].AsUUID();
161 UUID godSessionID = userData["GodSessionID"].AsUUID();
162 uint kickFlags = userData["KickFlags"].AsUInteger();
163 string reason = userData["Reason"].AsString();
164
165 ScenePresence god = m_scene.GetScenePresence(godID);
166 if (god == null || god.ControllingClient.SessionId != godSessionID)
167 return String.Empty;
168
169 KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason));
170 }
171 else
172 {
173 m_log.ErrorFormat("[GOD]: Unhandled UntrustedSimulatorMessage: {0}", message);
174 }
175 return String.Empty;
176 }
177
101 public void RequestGodlikePowers( 178 public void RequestGodlikePowers(
102 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) 179 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient)
103 { 180 {
@@ -146,76 +223,86 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
146 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 223 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
147 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 224 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
148 { 225 {
149 UUID kickUserID = ALL_AGENTS; 226 if (!m_scene.Permissions.IsGod(godID))
150 227 return;
228
151 ScenePresence sp = m_scene.GetScenePresence(agentID); 229 ScenePresence sp = m_scene.GetScenePresence(agentID);
152 230
153 if (sp != null || agentID == kickUserID) 231 if (sp == null && agentID != ALL_AGENTS)
154 { 232 {
155 if (m_scene.Permissions.IsGod(godID)) 233 IMessageTransferModule transferModule =
234 m_scene.RequestModuleInterface<IMessageTransferModule>();
235 if (transferModule != null)
156 { 236 {
157 if (kickflags == 0) 237 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
158 { 238 transferModule.SendInstantMessage(new GridInstantMessage(
159 if (agentID == kickUserID) 239 m_scene, godID, "God", agentID, (byte)250, false,
160 { 240 Utils.BytesToString(reason), UUID.Zero, true,
161 string reasonStr = Utils.BytesToString(reason); 241 new Vector3(), new byte[] {(byte)kickflags}, true),
162 242 delegate(bool success) {} );
163 m_scene.ForEachClient( 243 }
164 delegate(IClientAPI controller) 244 return;
165 { 245 }
166 if (controller.AgentId != godID)
167 controller.Kick(reasonStr);
168 }
169 );
170
171 // This is a bit crude. It seems the client will be null before it actually stops the thread
172 // The thread will kill itself eventually :/
173 // Is there another way to make sure *all* clients get this 'inter region' message?
174 m_scene.ForEachRootClient(
175 delegate(IClientAPI client)
176 {
177 if (client.AgentId != godID)
178 {
179 client.Close();
180 }
181 }
182 );
183 }
184 else
185 {
186 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent);
187 246
188 sp.ControllingClient.Kick(Utils.BytesToString(reason)); 247 switch (kickflags)
189 sp.ControllingClient.Close(); 248 {
190 } 249 case 0:
191 } 250 if (sp != null)
192 251 {
193 if (kickflags == 1) 252 KickPresence(sp, Utils.BytesToString(reason));
194 {
195 sp.AllowMovement = false;
196 if (DialogModule != null)
197 {
198 DialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
199 DialogModule.SendAlertToUser(godID, "User Frozen");
200 }
201 }
202
203 if (kickflags == 2)
204 {
205 sp.AllowMovement = true;
206 if (DialogModule != null)
207 {
208 DialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
209 DialogModule.SendAlertToUser(godID, "User Unfrozen");
210 }
211 }
212 } 253 }
213 else 254 else if (agentID == ALL_AGENTS)
214 { 255 {
215 if (DialogModule != null) 256 m_scene.ForEachRootScenePresence(
216 DialogModule.SendAlertToUser(godID, "Kick request denied"); 257 delegate(ScenePresence p)
258 {
259 if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID)))
260 KickPresence(p, Utils.BytesToString(reason));
261 }
262 );
263 }
264 break;
265 case 1:
266 if (sp != null)
267 {
268 sp.AllowMovement = false;
269 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
270 m_dialogModule.SendAlertToUser(godID, "User Frozen");
217 } 271 }
272 break;
273 case 2:
274 if (sp != null)
275 {
276 sp.AllowMovement = true;
277 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
278 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
279 }
280 break;
281 default:
282 break;
283 }
284 }
285
286 private void KickPresence(ScenePresence sp, string reason)
287 {
288 if (sp.IsChildAgent)
289 return;
290 sp.ControllingClient.Kick(reason);
291 sp.MakeChildAgent();
292 sp.ControllingClient.Close();
293 }
294
295 private void OnIncomingInstantMessage(GridInstantMessage msg)
296 {
297 if (msg.dialog == (uint)250) // Nonlocal kick
298 {
299 UUID agentID = new UUID(msg.toAgentID);
300 string reason = msg.message;
301 UUID godID = new UUID(msg.fromAgentID);
302 uint kickMode = (uint)msg.binaryBucket[0];
303
304 KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason));
218 } 305 }
219 } 306 }
220 } 307 }
221} \ No newline at end of file 308}
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
deleted file mode 100644
index b735c61..0000000
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ /dev/null
@@ -1,260 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37
38using Mono.Addins;
39
40namespace OpenSim.Region.CoreModules.Avatar.Groups
41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
43 public class GroupsModule : ISharedRegionModule
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private Dictionary<UUID, GroupMembershipData> m_GroupMap =
49 new Dictionary<UUID, GroupMembershipData>();
50
51 private Dictionary<UUID, IClientAPI> m_ClientMap =
52 new Dictionary<UUID, IClientAPI>();
53
54 private UUID opensimulatorGroupID =
55 new UUID("00000000-68f9-1111-024e-222222111123");
56
57 private List<Scene> m_SceneList = new List<Scene>();
58
59 private static GroupMembershipData osGroup =
60 new GroupMembershipData();
61
62 private bool m_Enabled = false;
63
64 #region ISharedRegionModule Members
65
66 public void Initialise(IConfigSource config)
67 {
68 IConfig groupsConfig = config.Configs["Groups"];
69
70 if (groupsConfig == null)
71 {
72 m_log.Info("[GROUPS]: No configuration found. Using defaults");
73 }
74 else
75 {
76 m_Enabled = groupsConfig.GetBoolean("Enabled", false);
77 if (!m_Enabled)
78 {
79 m_log.Info("[GROUPS]: Groups disabled in configuration");
80 return;
81 }
82
83 if (groupsConfig.GetString("Module", "Default") != "Default")
84 {
85 m_Enabled = false;
86 return;
87 }
88 }
89
90 }
91
92 public void AddRegion(Scene scene)
93 {
94 if (!m_Enabled)
95 return;
96
97 lock (m_SceneList)
98 {
99 if (!m_SceneList.Contains(scene))
100 {
101 if (m_SceneList.Count == 0)
102 {
103 osGroup.GroupID = opensimulatorGroupID;
104 osGroup.GroupName = "OpenSimulator Testing";
105 osGroup.GroupPowers =
106 (uint)(GroupPowers.AllowLandmark |
107 GroupPowers.AllowSetHome);
108 m_GroupMap[opensimulatorGroupID] = osGroup;
109 }
110 m_SceneList.Add(scene);
111 }
112 }
113
114 scene.EventManager.OnNewClient += OnNewClient;
115 scene.EventManager.OnClientClosed += OnClientClosed;
116 // scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
117 }
118
119 public void RemoveRegion(Scene scene)
120 {
121 if (!m_Enabled)
122 return;
123
124 lock (m_SceneList)
125 {
126 if (m_SceneList.Contains(scene))
127 m_SceneList.Remove(scene);
128 }
129
130 scene.EventManager.OnNewClient -= OnNewClient;
131 scene.EventManager.OnClientClosed -= OnClientClosed;
132 }
133
134 public void RegionLoaded(Scene scene)
135 {
136 }
137
138 public void PostInitialise()
139 {
140 }
141
142 public void Close()
143 {
144 if (!m_Enabled)
145 return;
146
147// m_log.Debug("[GROUPS]: Shutting down group module.");
148
149 lock (m_ClientMap)
150 {
151 m_ClientMap.Clear();
152 }
153
154 lock (m_GroupMap)
155 {
156 m_GroupMap.Clear();
157 }
158 }
159
160 public string Name
161 {
162 get { return "GroupsModule"; }
163 }
164
165 public Type ReplaceableInterface
166 {
167 get { return null; }
168 }
169
170 #endregion
171
172 private void OnNewClient(IClientAPI client)
173 {
174 // Subscribe to instant messages
175// client.OnInstantMessage += OnInstantMessage;
176 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
177 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
178 lock (m_ClientMap)
179 {
180 if (!m_ClientMap.ContainsKey(client.AgentId))
181 {
182 m_ClientMap.Add(client.AgentId, client);
183 }
184 }
185
186 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
187 updateGroups[0] = osGroup;
188
189 client.SendGroupMembership(updateGroups);
190 }
191
192 private void OnAgentDataUpdateRequest(IClientAPI remoteClient,
193 UUID AgentID, UUID SessionID)
194 {
195 UUID ActiveGroupID;
196 string ActiveGroupName;
197 ulong ActiveGroupPowers;
198
199 string firstname = remoteClient.FirstName;
200 string lastname = remoteClient.LastName;
201
202 string ActiveGroupTitle = "I IZ N0T";
203
204 ActiveGroupID = osGroup.GroupID;
205 ActiveGroupName = osGroup.GroupName;
206 ActiveGroupPowers = osGroup.GroupPowers;
207
208 remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname,
209 lastname, ActiveGroupPowers, ActiveGroupName,
210 ActiveGroupTitle);
211 }
212
213// private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
214// {
215// }
216
217// private void OnGridInstantMessage(GridInstantMessage msg)
218// {
219// // Trigger the above event handler
220// OnInstantMessage(null, msg);
221// }
222
223 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client)
224 {
225 string groupnamereply = "Unknown";
226 UUID groupUUID = UUID.Zero;
227
228 lock (m_GroupMap)
229 {
230 if (m_GroupMap.ContainsKey(id))
231 {
232 GroupMembershipData grp = m_GroupMap[id];
233 groupnamereply = grp.GroupName;
234 groupUUID = grp.GroupID;
235 }
236 }
237 remote_client.SendGroupNameReply(groupUUID, groupnamereply);
238 }
239
240 private void OnClientClosed(UUID agentID, Scene scene)
241 {
242 lock (m_ClientMap)
243 {
244 if (m_ClientMap.ContainsKey(agentID))
245 {
246// IClientAPI cli = m_ClientMap[agentID];
247// if (cli != null)
248// {
249// //m_log.Info("[GROUPS]: Removing all reference to groups for " + cli.Name);
250// }
251// else
252// {
253// //m_log.Info("[GROUPS]: Removing all reference to groups for " + agentID.ToString());
254// }
255 m_ClientMap.Remove(agentID);
256 }
257 }
258 }
259 }
260}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..55e30a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers;
30using log4net; 31using log4net;
31using Mono.Addins; 32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
@@ -44,6 +45,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
44 private static readonly ILog m_log = LogManager.GetLogger( 45 private static readonly ILog m_log = LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
46 47
48 private Timer m_logTimer = new Timer(10000);
49 private List<GridInstantMessage> m_logData = new List<GridInstantMessage>();
50 private string m_restUrl;
51
47 /// <value> 52 /// <value>
48 /// Is this module enabled? 53 /// Is this module enabled?
49 /// </value> 54 /// </value>
@@ -63,9 +68,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
63 "InstantMessageModule", "InstantMessageModule") != 68 "InstantMessageModule", "InstantMessageModule") !=
64 "InstantMessageModule") 69 "InstantMessageModule")
65 return; 70 return;
71 m_restUrl = config.Configs["Messaging"].GetString("LogURL", String.Empty);
66 } 72 }
67 73
68 m_enabled = true; 74 m_enabled = true;
75 m_logTimer.AutoReset = false;
76 m_logTimer.Elapsed += LogTimerElapsed;
69 } 77 }
70 78
71 public void AddRegion(Scene scene) 79 public void AddRegion(Scene scene)
@@ -150,6 +158,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
150 { 158 {
151 byte dialog = im.dialog; 159 byte dialog = im.dialog;
152 160
161 if (client != null && dialog == (byte)InstantMessageDialog.MessageFromAgent)
162 LogInstantMesssage(im);
163
153 if (dialog != (byte)InstantMessageDialog.MessageFromAgent 164 if (dialog != (byte)InstantMessageDialog.MessageFromAgent
154 && dialog != (byte)InstantMessageDialog.StartTyping 165 && dialog != (byte)InstantMessageDialog.StartTyping
155 && dialog != (byte)InstantMessageDialog.StopTyping 166 && dialog != (byte)InstantMessageDialog.StopTyping
@@ -159,6 +170,32 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 return; 170 return;
160 } 171 }
161 172
173 //DateTime dt = DateTime.UtcNow;
174
175 // Ticks from UtcNow, but make it look like local. Evil, huh?
176 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
177
178 //try
179 //{
180 // // Convert that to the PST timezone
181 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
182 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
183 //}
184 //catch
185 //{
186 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
187 //}
188
189 //// And make it look local again to fool the unix time util
190 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
191
192 // If client is null, this message comes from storage and IS offline
193 if (client != null)
194 im.offline = 0;
195
196 if (im.offline == 0)
197 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
198
162 if (m_TransferModule != null) 199 if (m_TransferModule != null)
163 { 200 {
164 if (client != null) 201 if (client != null)
@@ -202,5 +239,35 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
202 // 239 //
203 OnInstantMessage(null, msg); 240 OnInstantMessage(null, msg);
204 } 241 }
242
243 private void LogInstantMesssage(GridInstantMessage im)
244 {
245 if (m_logData.Count < 20)
246 {
247 // Restart the log write timer
248 m_logTimer.Stop();
249 }
250 if (!m_logTimer.Enabled)
251 m_logTimer.Start();
252
253 lock (m_logData)
254 {
255 m_logData.Add(im);
256 }
257 }
258
259 private void LogTimerElapsed(object source, ElapsedEventArgs e)
260 {
261 lock (m_logData)
262 {
263 if (m_restUrl != String.Empty && m_logData.Count > 0)
264 {
265 bool success = SynchronousRestObjectRequester.MakeRequest<List<GridInstantMessage>, bool>("POST", m_restUrl + "/LogMessages/", m_logData);
266 if (!success)
267 m_log.ErrorFormat("[INSTANT MESSAGE]: Failed to save log data");
268 }
269 m_logData.Clear();
270 }
271 }
205 } 272 }
206} 273}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index fa935cd..1627f6c 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private bool m_Enabled = false; 52 private bool m_Enabled = false;
53 protected string m_MessageKey = String.Empty;
53 protected List<Scene> m_Scenes = new List<Scene>(); 54 protected List<Scene> m_Scenes = new List<Scene>();
54 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 55 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
55 56
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
69 public virtual void Initialise(IConfigSource config) 70 public virtual void Initialise(IConfigSource config)
70 { 71 {
71 IConfig cnf = config.Configs["Messaging"]; 72 IConfig cnf = config.Configs["Messaging"];
72 if (cnf != null && cnf.GetString( 73 if (cnf != null)
73 "MessageTransferModule", "MessageTransferModule") !=
74 "MessageTransferModule")
75 { 74 {
76 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 75 if (cnf.GetString("MessageTransferModule",
77 return; 76 "MessageTransferModule") != "MessageTransferModule")
78 } 77 {
78 return;
79 }
79 80
81 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82 }
83 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
80 m_Enabled = true; 84 m_Enabled = true;
81 } 85 }
82 86
@@ -135,6 +139,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
135 { 139 {
136 UUID toAgentID = new UUID(im.toAgentID); 140 UUID toAgentID = new UUID(im.toAgentID);
137 141
142 if (toAgentID == UUID.Zero)
143 return;
144
138 // Try root avatar only first 145 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 146 foreach (Scene scene in m_Scenes)
140 { 147 {
@@ -249,6 +256,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 256 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 257 && requestData.ContainsKey("binary_bucket"))
251 { 258 {
259 if (m_MessageKey != String.Empty)
260 {
261 XmlRpcResponse error_resp = new XmlRpcResponse();
262 Hashtable error_respdata = new Hashtable();
263 error_respdata["success"] = "FALSE";
264 error_resp.Value = error_respdata;
265
266 if (!requestData.Contains("message_key"))
267 return error_resp;
268 if (m_MessageKey != (string)requestData["message_key"])
269 return error_resp;
270 }
271
252 // Do the easy way of validating the UUIDs 272 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 273 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 274 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -425,24 +445,37 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 445 return resp;
426 } 446 }
427 447
428 /// <summary> 448 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
429 /// delegate for sending a grid instant message asynchronously
430 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID);
432 449
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 450 private class GIM {
434 { 451 public GridInstantMessage im;
435 GridInstantMessageDelegate icon = 452 public MessageResultNotification result;
436 (GridInstantMessageDelegate)iar.AsyncState; 453 };
437 icon.EndInvoke(iar);
438 }
439 454
455 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
456 private int numInstantMessageThreads = 0;
440 457
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 458 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
442 { 459 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 460 lock (pendingInstantMessages) {
461 if (numInstantMessageThreads >= 4) {
462 GIM gim = new GIM();
463 gim.im = im;
464 gim.result = result;
465 pendingInstantMessages.Enqueue(gim);
466 } else {
467 ++ numInstantMessageThreads;
468 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
469 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
470 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
471 }
472 }
473 }
444 474
445 d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); 475 private void GridInstantMessageCompleted(IAsyncResult iar)
476 {
477 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
478 d.EndInvoke(iar);
446 } 479 }
447 480
448 /// <summary> 481 /// <summary>
@@ -457,8 +490,31 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
457 /// Pass in 0 the first time this method is called. It will be called recursively with the last 490 /// Pass in 0 the first time this method is called. It will be called recursively with the last
458 /// regionhandle tried 491 /// regionhandle tried
459 /// </param> 492 /// </param>
460 protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) 493 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
461 { 494 {
495 GIM gim;
496 do {
497 try {
498 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
499 } catch (Exception e) {
500 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
501 }
502 lock (pendingInstantMessages) {
503 if (pendingInstantMessages.Count > 0) {
504 gim = pendingInstantMessages.Dequeue();
505 im = gim.im;
506 result = gim.result;
507 } else {
508 gim = null;
509 -- numInstantMessageThreads;
510 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
511 }
512 }
513 } while (gim != null);
514 }
515 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
516 {
517
462 UUID toAgentID = new UUID(im.toAgentID); 518 UUID toAgentID = new UUID(im.toAgentID);
463 519
464 PresenceInfo upd = null; 520 PresenceInfo upd = null;
@@ -525,7 +581,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
525 581
526 if (upd != null) 582 if (upd != null)
527 { 583 {
528 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, 584 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
529 upd.RegionID); 585 upd.RegionID);
530 if (reginfo != null) 586 if (reginfo != null)
531 { 587 {
@@ -674,6 +730,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
674 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
675 gim["region_id"] = msg.RegionID.ToString(); 731 gim["region_id"] = msg.RegionID.ToString();
676 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733 if (m_MessageKey != String.Empty)
734 gim["message_key"] = m_MessageKey;
677 return gim; 735 return gim;
678 } 736 }
679 737
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 7d763fa..2d46276 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -173,7 +173,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
173 173
174 private void RetrieveInstantMessages(IClientAPI client) 174 private void RetrieveInstantMessages(IClientAPI client)
175 { 175 {
176 if (m_RestURL != "") 176 if (m_RestURL == String.Empty)
177 {
178 return;
179 }
180 else
177 { 181 {
178 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 182 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
179 183
@@ -181,25 +185,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
181 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 185 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
182 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 186 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
183 187
184 if (msglist == null) 188 if (msglist != null)
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
186
187 foreach (GridInstantMessage im in msglist)
188 { 189 {
189 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 190 foreach (GridInstantMessage im in msglist)
190 // send it directly or else the item will be given twice
191 client.SendInstantMessage(im);
192 else
193 { 191 {
194 // Send through scene event manager so all modules get a chance 192 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
195 // to look at this message before it gets delivered. 193 // send it directly or else the item will be given twice
196 // 194 client.SendInstantMessage(im);
197 // Needed for proper state management for stored group 195 else
198 // invitations 196 {
199 // 197 // Send through scene event manager so all modules get a chance
200 Scene s = FindScene(client.AgentId); 198 // to look at this message before it gets delivered.
201 if (s != null) 199 //
202 s.EventManager.TriggerIncomingInstantMessage(im); 200 // Needed for proper state management for stored group
201 // invitations
202 //
203
204 im.offline = 1;
205
206 Scene s = FindScene(client.AgentId);
207 if (s != null)
208 s.EventManager.TriggerIncomingInstantMessage(im);
209 }
203 } 210 }
204 } 211 }
205 } 212 }
@@ -211,24 +218,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
211 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 218 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
212 im.dialog != (byte)InstantMessageDialog.GroupNotice && 219 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
213 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 220 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
214 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 221 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
222 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
215 { 223 {
216 return; 224 return;
217 } 225 }
218 226
219 if (!m_ForwardOfflineGroupMessages)
220 {
221 if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
222 im.dialog == (byte)InstantMessageDialog.GroupInvitation)
223 return;
224 }
225
226 Scene scene = FindScene(new UUID(im.fromAgentID)); 227 Scene scene = FindScene(new UUID(im.fromAgentID));
227 if (scene == null) 228 if (scene == null)
228 scene = m_SceneList[0]; 229 scene = m_SceneList[0];
229 230
230 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 231 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
231 "POST", m_RestURL+"/SaveMessage/", im); 232 "POST", m_RestURL+"/SaveMessage/?scope=" +
233 scene.RegionInfo.ScopeID.ToString(), im);
232 234
233 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 235 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
234 { 236 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 98285e9..659b178 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -652,4 +652,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
652 m_assetsLoaded = true; 652 m_assetsLoaded = true;
653 } 653 }
654 } 654 }
655} \ No newline at end of file 655}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 849449b..f4f9e2d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -519,6 +519,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
519 return null; 519 return null;
520 } 520 }
521 521
522 return account;
523 /*
522 try 524 try
523 { 525 {
524 string encpass = Util.Md5Hash(pass); 526 string encpass = Util.Md5Hash(pass);
@@ -539,6 +541,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
539 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); 541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message);
540 return null; 542 return null;
541 } 543 }
544 */
542 } 545 }
543 546
544 /// <summary> 547 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bcb7f42..ae58dfd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -177,8 +177,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
177 if (im.binaryBucket.Length < 17) // Invalid 177 if (im.binaryBucket.Length < 17) // Invalid
178 return; 178 return;
179 179
180 UUID receipientID = new UUID(im.toAgentID); 180 UUID recipientID = new UUID(im.toAgentID);
181 ScenePresence user = scene.GetScenePresence(receipientID); 181 ScenePresence user = scene.GetScenePresence(recipientID);
182 UUID copyID; 182 UUID copyID;
183 183
184 // First byte is the asset type 184 // First byte is the asset type
@@ -193,7 +193,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
193 folderID, new UUID(im.toAgentID)); 193 folderID, new UUID(im.toAgentID));
194 194
195 InventoryFolderBase folderCopy 195 InventoryFolderBase folderCopy
196 = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); 196 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
197 197
198 if (folderCopy == null) 198 if (folderCopy == null)
199 { 199 {
@@ -246,6 +246,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
246 im.imSessionID = itemID.Guid; 246 im.imSessionID = itemID.Guid;
247 } 247 }
248 248
249 im.offline = 0;
250
249 // Send the IM to the recipient. The item is already 251 // Send the IM to the recipient. The item is already
250 // in their inventory, so it will not be lost if 252 // in their inventory, so it will not be lost if
251 // they are offline. 253 // they are offline.
@@ -265,8 +267,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
265 }); 267 });
266 } 268 }
267 } 269 }
268 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) 270 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
271 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
269 { 272 {
273 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
274 IInventoryService invService = scene.InventoryService;
275
276 // Special case: folder redirect.
277 // RLV uses this
278 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
279 {
280 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, client.AgentId);
281 folder = invService.GetFolder(folder);
282
283 if (folder != null)
284 {
285 if (im.binaryBucket.Length >= 16)
286 {
287 UUID destFolderID = new UUID(im.binaryBucket, 0);
288 if (destFolderID != UUID.Zero)
289 {
290 InventoryFolderBase destFolder = new InventoryFolderBase(destFolderID, client.AgentId);
291 destFolder = invService.GetFolder(destFolder);
292 if (destFolder != null)
293 {
294 if (folder.ParentID != destFolder.ID)
295 {
296 folder.ParentID = destFolder.ID;
297 invService.MoveFolder(folder);
298 client.SendBulkUpdateInventory(folder);
299 }
300 }
301 }
302 }
303 }
304 }
305
270 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 306 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
271 307
272 if (user != null) // Local 308 if (user != null) // Local
@@ -276,27 +312,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
276 else 312 else
277 { 313 {
278 if (m_TransferModule != null) 314 if (m_TransferModule != null)
279 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 315 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
280
281 // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
282 // and is apparently supposed to fix bulk inventory updates after accepting items. But
283 // instead it appears to cause two copies of an accepted folder for the receiving user in
284 // at least some cases. Folder/item update is already done when the offer is made (see code above)
285
286// // Send BulkUpdateInventory
287// IInventoryService invService = scene.InventoryService;
288// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
289//
290// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
291// folder = invService.GetFolder(folder);
292//
293// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
294//
295// // If the user has left the scene by the time the message comes back then we can't send
296// // them the update.
297// if (fromUser != null)
298// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
299 });
300 } 316 }
301 } 317 }
302 318
@@ -409,6 +425,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
409 previousParentFolderID = folder.ParentID; 425 previousParentFolderID = folder.ParentID;
410 folder.ParentID = trashFolder.ID; 426 folder.ParentID = trashFolder.ID;
411 invService.MoveFolder(folder); 427 invService.MoveFolder(folder);
428 client.SendBulkUpdateInventory(folder);
412 } 429 }
413 } 430 }
414 431
@@ -522,22 +539,113 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
522 /// 539 ///
523 /// </summary> 540 /// </summary>
524 /// <param name="msg"></param> 541 /// <param name="msg"></param>
525 private void OnGridInstantMessage(GridInstantMessage msg) 542 private void OnGridInstantMessage(GridInstantMessage im)
526 { 543 {
527 // Check if this is ours to handle 544 // Check if this is ours to handle
528 // 545 //
529 Scene scene = FindClientScene(new UUID(msg.toAgentID)); 546 Scene scene = FindClientScene(new UUID(im.toAgentID));
530 547
531 if (scene == null) 548 if (scene == null)
532 return; 549 return;
533 550
534 // Find agent to deliver to 551 // Find agent to deliver to
535 // 552 //
536 ScenePresence user = scene.GetScenePresence(new UUID(msg.toAgentID)); 553 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
554 if (user == null)
555 return;
556
557 // This requires a little bit of processing because we have to make the
558 // new item visible in the recipient's inventory here
559 //
560 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
561 {
562 if (im.binaryBucket.Length < 17) // Invalid
563 return;
564
565 UUID recipientID = new UUID(im.toAgentID);
566
567 // First byte is the asset type
568 AssetType assetType = (AssetType)im.binaryBucket[0];
569
570 if (AssetType.Folder == assetType)
571 {
572 UUID folderID = new UUID(im.binaryBucket, 1);
537 573
538 // Just forward to local handling 574 InventoryFolderBase given =
539 OnInstantMessage(user.ControllingClient, msg); 575 new InventoryFolderBase(folderID, recipientID);
576 InventoryFolderBase folder =
577 scene.InventoryService.GetFolder(given);
540 578
579 if (folder != null)
580 user.ControllingClient.SendBulkUpdateInventory(folder);
581 }
582 else
583 {
584 UUID itemID = new UUID(im.binaryBucket, 1);
585
586 InventoryItemBase given =
587 new InventoryItemBase(itemID, recipientID);
588 InventoryItemBase item =
589 scene.InventoryService.GetItem(given);
590
591 if (item != null)
592 {
593 user.ControllingClient.SendBulkUpdateInventory(item);
594 }
595 }
596 user.ControllingClient.SendInstantMessage(im);
597 }
598 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
599 {
600 if (im.binaryBucket.Length < 1) // Invalid
601 return;
602
603 UUID recipientID = new UUID(im.toAgentID);
604
605 // Bucket is the asset type
606 AssetType assetType = (AssetType)im.binaryBucket[0];
607
608 if (AssetType.Folder == assetType)
609 {
610 UUID folderID = new UUID(im.imSessionID);
611
612 InventoryFolderBase given =
613 new InventoryFolderBase(folderID, recipientID);
614 InventoryFolderBase folder =
615 scene.InventoryService.GetFolder(given);
616
617 if (folder != null)
618 user.ControllingClient.SendBulkUpdateInventory(folder);
619 }
620 else
621 {
622 UUID itemID = new UUID(im.imSessionID);
623
624 InventoryItemBase given =
625 new InventoryItemBase(itemID, recipientID);
626 InventoryItemBase item =
627 scene.InventoryService.GetItem(given);
628
629 if (item != null)
630 {
631 user.ControllingClient.SendBulkUpdateInventory(item);
632 }
633 }
634
635 // Fix up binary bucket since this may be 17 chars long here
636 Byte[] bucket = new Byte[1];
637 bucket[0] = im.binaryBucket[0];
638 im.binaryBucket = bucket;
639
640 user.ControllingClient.SendInstantMessage(im);
641 }
642 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
643 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
644 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
645 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
646 {
647 user.ControllingClient.SendInstantMessage(im);
648 }
541 } 649 }
542 } 650 }
543} 651}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index e4b0cfa..f3adb95 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -163,16 +163,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
163 scene.RegionInfo.RegionHandle, 163 scene.RegionInfo.RegionHandle,
164 (uint)presence.AbsolutePosition.X, 164 (uint)presence.AbsolutePosition.X,
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)Math.Ceiling(presence.AbsolutePosition.Z)); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("TP invite with message {0}", message); 168 m_log.DebugFormat("[LURE]: TP invite with message {0}", message);
169
170 GridInstantMessage m;
171
172 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.GodLevel >= 200 && (!scene.Permissions.IsAdministrator(targetid)))
173 {
174 m = new GridInstantMessage(scene, client.AgentId,
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 }
169 188
170 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
171 client.FirstName+" "+client.LastName, targetid,
172 (byte)InstantMessageDialog.RequestTeleport, false,
173 message, dest, false, presence.AbsolutePosition,
174 new Byte[0], true);
175
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)