diff options
Merge branch 'master' into newmultiattach
Conflicts:
OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
Diffstat (limited to 'OpenSim/Region')
39 files changed, 1466 insertions, 580 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 4075edb..11dd052 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -159,6 +159,7 @@ namespace OpenSim | |||
159 | 159 | ||
160 | MainConsole.Instance = m_console; | 160 | MainConsole.Instance = m_console; |
161 | 161 | ||
162 | LogEnvironmentInformation(); | ||
162 | RegisterCommonAppenders(Config.Configs["Startup"]); | 163 | RegisterCommonAppenders(Config.Configs["Startup"]); |
163 | RegisterConsoleCommands(); | 164 | RegisterConsoleCommands(); |
164 | 165 | ||
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 137bd81..c555915 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs | |||
@@ -134,10 +134,6 @@ namespace OpenSim | |||
134 | /// <param name="configSource"></param> | 134 | /// <param name="configSource"></param> |
135 | public OpenSimBase(IConfigSource configSource) : base() | 135 | public OpenSimBase(IConfigSource configSource) : base() |
136 | { | 136 | { |
137 | // FIXME: This should be done down in ServerBase but we need to sort out and refactor the log4net | ||
138 | // XmlConfigurator calls first accross servers. | ||
139 | m_log.InfoFormat("[SERVER BASE]: Starting in {0}", m_startupDirectory); | ||
140 | |||
141 | LoadConfigSettings(configSource); | 137 | LoadConfigSettings(configSource); |
142 | } | 138 | } |
143 | 139 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index ed8ec16..141af8a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs | |||
@@ -49,8 +49,10 @@ namespace OpenSim.Region.ClientStack.Linden.Tests | |||
49 | private TestScene m_scene; | 49 | private TestScene m_scene; |
50 | 50 | ||
51 | [SetUp] | 51 | [SetUp] |
52 | public void SetUp() | 52 | public override void SetUp() |
53 | { | 53 | { |
54 | base.SetUp(); | ||
55 | |||
54 | uint port = 9999; | 56 | uint port = 9999; |
55 | uint sslPort = 9998; | 57 | uint sslPort = 9998; |
56 | 58 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6742d99..7ea538c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -4581,7 +4581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4581 | rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); | 4581 | rinfopack.AgentData = new RegionInfoPacket.AgentDataBlock(); |
4582 | rinfopack.AgentData.AgentID = AgentId; | 4582 | rinfopack.AgentData.AgentID = AgentId; |
4583 | rinfopack.AgentData.SessionID = SessionId; | 4583 | rinfopack.AgentData.SessionID = SessionId; |
4584 | 4584 | rinfopack.RegionInfo3 = new RegionInfoPacket.RegionInfo3Block[0]; | |
4585 | 4585 | ||
4586 | OutPacket(rinfopack, ThrottleOutPacketType.Task); | 4586 | OutPacket(rinfopack, ThrottleOutPacketType.Task); |
4587 | } | 4587 | } |
@@ -7069,7 +7069,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
7069 | 7069 | ||
7070 | if (handlerUpdatePrimFlags != null) | 7070 | if (handlerUpdatePrimFlags != null) |
7071 | { | 7071 | { |
7072 | byte[] data = Pack.ToBytes(); | 7072 | // byte[] data = Pack.ToBytes(); |
7073 | // 46,47,48 are special positions within the packet | 7073 | // 46,47,48 are special positions within the packet |
7074 | // This may change so perhaps we need a better way | 7074 | // This may change so perhaps we need a better way |
7075 | // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) | 7075 | // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index a7628d2..72516cd 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -278,25 +278,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
278 | m_shouldCollectStats = false; | 278 | m_shouldCollectStats = false; |
279 | if (config != null) | 279 | if (config != null) |
280 | { | 280 | { |
281 | if (config.Contains("enabled") && config.GetBoolean("enabled")) | 281 | m_shouldCollectStats = config.GetBoolean("Enabled", false); |
282 | { | 282 | binStatsMaxFilesize = TimeSpan.FromSeconds(config.GetInt("packet_headers_period_seconds", 300)); |
283 | if (config.Contains("collect_packet_headers")) | 283 | binStatsDir = config.GetString("stats_dir", "."); |
284 | m_shouldCollectStats = config.GetBoolean("collect_packet_headers"); | 284 | m_aggregatedBWStats = config.GetBoolean("aggregatedBWStats", false); |
285 | if (config.Contains("packet_headers_period_seconds")) | 285 | } |
286 | { | 286 | #endregion BinaryStats |
287 | binStatsMaxFilesize = TimeSpan.FromSeconds(config.GetInt("region_stats_period_seconds")); | ||
288 | } | ||
289 | if (config.Contains("stats_dir")) | ||
290 | { | ||
291 | binStatsDir = config.GetString("stats_dir"); | ||
292 | } | ||
293 | } | ||
294 | else | ||
295 | { | ||
296 | m_shouldCollectStats = false; | ||
297 | } | ||
298 | } | ||
299 | #endregion BinaryStats | ||
300 | 287 | ||
301 | m_throttle = new TokenBucket(null, sceneThrottleBps); | 288 | m_throttle = new TokenBucket(null, sceneThrottleBps); |
302 | ThrottleRates = new ThrottleRates(configSource); | 289 | ThrottleRates = new ThrottleRates(configSource); |
@@ -1266,8 +1253,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1266 | static object binStatsLogLock = new object(); | 1253 | static object binStatsLogLock = new object(); |
1267 | static string binStatsDir = ""; | 1254 | static string binStatsDir = ""; |
1268 | 1255 | ||
1256 | //for Aggregated In/Out BW logging | ||
1257 | static bool m_aggregatedBWStats = false; | ||
1258 | static long m_aggregatedBytesIn = 0; | ||
1259 | static long m_aggregatedByestOut = 0; | ||
1260 | static object aggBWStatsLock = new object(); | ||
1261 | |||
1262 | public static long AggregatedLLUDPBytesIn | ||
1263 | { | ||
1264 | get { return m_aggregatedBytesIn; } | ||
1265 | } | ||
1266 | public static long AggregatedLLUDPBytesOut | ||
1267 | { | ||
1268 | get {return m_aggregatedByestOut;} | ||
1269 | } | ||
1270 | |||
1269 | public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size) | 1271 | public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size) |
1270 | { | 1272 | { |
1273 | if (m_aggregatedBWStats) | ||
1274 | { | ||
1275 | lock (aggBWStatsLock) | ||
1276 | { | ||
1277 | if (incoming) | ||
1278 | m_aggregatedBytesIn += size; | ||
1279 | else | ||
1280 | m_aggregatedByestOut += size; | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1271 | if (!m_shouldCollectStats) return; | 1284 | if (!m_shouldCollectStats) return; |
1272 | 1285 | ||
1273 | // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size | 1286 | // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index ab7e932..2dea14d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -289,21 +289,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
289 | if (!Enabled) | 289 | if (!Enabled) |
290 | return false; | 290 | return false; |
291 | 291 | ||
292 | if (AttachObjectInternal(sp, group, attachmentPt, silent, temp, append)) | 292 | return AttachObjectInternal(sp, group, attachmentPt, silent, temp, append); |
293 | { | ||
294 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | ||
295 | return true; | ||
296 | } | ||
297 | |||
298 | return false; | ||
299 | } | 293 | } |
300 | |||
301 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool append) | ||
302 | { | ||
303 | // m_log.DebugFormat( | ||
304 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | ||
305 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | ||
306 | 294 | ||
295 | /// <summary> | ||
296 | /// Internal method which actually does all the work for attaching an object. | ||
297 | /// </summary> | ||
298 | /// <returns>The object attached.</returns> | ||
299 | /// <param name='sp'></param> | ||
300 | /// <param name='group'>The object to attach.</param> | ||
301 | /// <param name='attachmentPt'></param> | ||
302 | /// <param name='silent'></param> | ||
303 | /// <param name='temp'></param> | ||
304 | /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> | ||
305 | private bool AttachObjectInternal( | ||
306 | IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool resumeScripts) | ||
307 | { | ||
307 | if (group.GetSittingAvatarsCount() != 0) | 308 | if (group.GetSittingAvatarsCount() != 0) |
308 | { | 309 | { |
309 | // m_log.WarnFormat( | 310 | // m_log.WarnFormat( |
@@ -314,6 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
314 | } | 315 | } |
315 | 316 | ||
316 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | 317 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); |
318 | |||
317 | if (attachments.Contains(group)) | 319 | if (attachments.Contains(group)) |
318 | { | 320 | { |
319 | // m_log.WarnFormat( | 321 | // m_log.WarnFormat( |
@@ -374,6 +376,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
374 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append); | 376 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append); |
375 | 377 | ||
376 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | 378 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); |
379 | |||
380 | if (resumeScripts) | ||
381 | { | ||
382 | // Fire after attach, so we don't get messy perms dialogs | ||
383 | // 4 == AttachedRez | ||
384 | group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | ||
385 | group.ResumeScripts(); | ||
386 | } | ||
387 | |||
388 | // Do this last so that event listeners have access to all the effects of the attachment | ||
389 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | ||
377 | } | 390 | } |
378 | 391 | ||
379 | return true; | 392 | return true; |
@@ -400,8 +413,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
400 | return null; | 413 | return null; |
401 | 414 | ||
402 | // m_log.DebugFormat( | 415 | // m_log.DebugFormat( |
403 | // "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", | 416 | // "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}", |
404 | // (AttachmentPoint)AttachmentPt, itemID, sp.Name); | 417 | // (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); |
405 | 418 | ||
406 | bool append = (AttachmentPt & 0x80) != 0; | 419 | bool append = (AttachmentPt & 0x80) != 0; |
407 | AttachmentPt &= 0x7f; | 420 | AttachmentPt &= 0x7f; |
@@ -533,6 +546,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
533 | return; | 546 | return; |
534 | } | 547 | } |
535 | 548 | ||
549 | // m_log.DebugFormat( | ||
550 | // "[ATTACHMENTS MODULE]: Detaching object {0} {1} for {2} in {3}", | ||
551 | // so.Name, so.LocalId, sp.Name, m_scene.Name); | ||
552 | |||
536 | // Scripts MUST be snapshotted before the object is | 553 | // Scripts MUST be snapshotted before the object is |
537 | // removed from the scene because doing otherwise will | 554 | // removed from the scene because doing otherwise will |
538 | // clobber the run flag | 555 | // clobber the run flag |
@@ -854,61 +871,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
854 | return null; | 871 | return null; |
855 | } | 872 | } |
856 | 873 | ||
857 | // Remove any previous attachments | ||
858 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
859 | string previousAttachmentScriptedState = null; | ||
860 | |||
861 | // At the moment we can only deal with a single attachment | ||
862 | if (attachments.Count != 0) | ||
863 | DetachSingleAttachmentToInv(sp, attachments[0]); | ||
864 | |||
865 | lock (sp.AttachmentsSyncLock) | ||
866 | { | ||
867 | // m_log.DebugFormat( | 874 | // m_log.DebugFormat( |
868 | // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 875 | // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", |
869 | // objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 876 | // objatt.Name, sp.Name, attachmentPt, m_scene.Name); |
870 | 877 | ||
871 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 878 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
872 | objatt.HasGroupChanged = false; | 879 | objatt.HasGroupChanged = false; |
873 | bool tainted = false; | 880 | bool tainted = false; |
874 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | 881 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) |
875 | tainted = true; | 882 | tainted = true; |
876 | 883 | ||
877 | // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal | 884 | // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal |
878 | // course of events. If not, then it's probably not worth trying to recover the situation | 885 | // course of events. If not, then it's probably not worth trying to recover the situation |
879 | // since this is more likely to trigger further exceptions and confuse later debugging. If | 886 | // since this is more likely to trigger further exceptions and confuse later debugging. If |
880 | // exceptions can be thrown in expected error conditions (not NREs) then make this consistent | 887 | // exceptions can be thrown in expected error conditions (not NREs) then make this consistent |
881 | // since other normal error conditions will simply return false instead. | 888 | // since other normal error conditions will simply return false instead. |
882 | // This will throw if the attachment fails | 889 | // This will throw if the attachment fails |
883 | try | 890 | try |
884 | { | 891 | { |
885 | AttachObjectInternal(sp, objatt, attachmentPt, false, false, append); | 892 | AttachObjectInternal(sp, objatt, attachmentPt, false, false, append); |
886 | } | 893 | } |
887 | catch (Exception e) | 894 | catch (Exception e) |
888 | { | 895 | { |
889 | m_log.ErrorFormat( | 896 | m_log.ErrorFormat( |
890 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | 897 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", |
891 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | 898 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); |
892 | |||
893 | // Make sure the object doesn't stick around and bail | ||
894 | sp.RemoveAttachment(objatt); | ||
895 | m_scene.DeleteSceneObject(objatt, false); | ||
896 | return null; | ||
897 | } | ||
898 | |||
899 | if (tainted) | ||
900 | objatt.HasGroupChanged = true; | ||
901 | 899 | ||
902 | // Fire after attach, so we don't get messy perms dialogs | 900 | // Make sure the object doesn't stick around and bail |
903 | // 4 == AttachedRez | 901 | sp.RemoveAttachment(objatt); |
904 | objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | 902 | m_scene.DeleteSceneObject(objatt, false); |
905 | objatt.ResumeScripts(); | 903 | return null; |
904 | } | ||
906 | 905 | ||
907 | // Do this last so that event listeners have access to all the effects of the attachment | 906 | if (tainted) |
908 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); | 907 | objatt.HasGroupChanged = true; |
909 | 908 | ||
910 | return objatt; | 909 | return objatt; |
911 | } | ||
912 | } | 910 | } |
913 | 911 | ||
914 | /// <summary> | 912 | /// <summary> |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index f48bb6f..0c1df6a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | |||
@@ -228,6 +228,120 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
228 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | 228 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); |
229 | } | 229 | } |
230 | 230 | ||
231 | [Test] | ||
232 | public void TestWearAttachmentFromGround() | ||
233 | { | ||
234 | TestHelpers.InMethod(); | ||
235 | // TestHelpers.EnableLogging(); | ||
236 | |||
237 | Scene scene = CreateTestScene(); | ||
238 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | ||
239 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); | ||
240 | |||
241 | SceneObjectGroup so2 = SceneHelpers.AddSceneObject(scene, "att2", sp.UUID); | ||
242 | |||
243 | { | ||
244 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); | ||
245 | |||
246 | m_numberOfAttachEventsFired = 0; | ||
247 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, false); | ||
248 | |||
249 | // Check status on scene presence | ||
250 | Assert.That(sp.HasAttachments(), Is.True); | ||
251 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
252 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
253 | SceneObjectGroup attSo = attachments[0]; | ||
254 | Assert.That(attSo.Name, Is.EqualTo(so.Name)); | ||
255 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
256 | Assert.That(attSo.IsAttachment); | ||
257 | Assert.That(attSo.UsesPhysics, Is.False); | ||
258 | Assert.That(attSo.IsTemporary, Is.False); | ||
259 | |||
260 | // Check item status | ||
261 | Assert.That( | ||
262 | sp.Appearance.GetAttachpoint(attSo.FromItemID), | ||
263 | Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
264 | |||
265 | InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); | ||
266 | Assert.That(attachmentItem, Is.Not.Null); | ||
267 | Assert.That(attachmentItem.Name, Is.EqualTo(so.Name)); | ||
268 | |||
269 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
270 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | ||
271 | |||
272 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(2)); | ||
273 | |||
274 | // Check events | ||
275 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
276 | } | ||
277 | |||
278 | // Test wearing a different attachment from the ground. | ||
279 | { | ||
280 | scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false); | ||
281 | |||
282 | // Check status on scene presence | ||
283 | Assert.That(sp.HasAttachments(), Is.True); | ||
284 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
285 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
286 | SceneObjectGroup attSo = attachments[0]; | ||
287 | Assert.That(attSo.Name, Is.EqualTo(so2.Name)); | ||
288 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
289 | Assert.That(attSo.IsAttachment); | ||
290 | Assert.That(attSo.UsesPhysics, Is.False); | ||
291 | Assert.That(attSo.IsTemporary, Is.False); | ||
292 | |||
293 | // Check item status | ||
294 | Assert.That( | ||
295 | sp.Appearance.GetAttachpoint(attSo.FromItemID), | ||
296 | Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
297 | |||
298 | InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); | ||
299 | Assert.That(attachmentItem, Is.Not.Null); | ||
300 | Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); | ||
301 | |||
302 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
303 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | ||
304 | |||
305 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
306 | |||
307 | // Check events | ||
308 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
309 | } | ||
310 | |||
311 | // Test rewearing an already worn attachment from ground. Nothing should happen. | ||
312 | { | ||
313 | scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false); | ||
314 | |||
315 | // Check status on scene presence | ||
316 | Assert.That(sp.HasAttachments(), Is.True); | ||
317 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
318 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
319 | SceneObjectGroup attSo = attachments[0]; | ||
320 | Assert.That(attSo.Name, Is.EqualTo(so2.Name)); | ||
321 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
322 | Assert.That(attSo.IsAttachment); | ||
323 | Assert.That(attSo.UsesPhysics, Is.False); | ||
324 | Assert.That(attSo.IsTemporary, Is.False); | ||
325 | |||
326 | // Check item status | ||
327 | Assert.That( | ||
328 | sp.Appearance.GetAttachpoint(attSo.FromItemID), | ||
329 | Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
330 | |||
331 | InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); | ||
332 | Assert.That(attachmentItem, Is.Not.Null); | ||
333 | Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); | ||
334 | |||
335 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
336 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | ||
337 | |||
338 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
339 | |||
340 | // Check events | ||
341 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
342 | } | ||
343 | } | ||
344 | |||
231 | /// <summary> | 345 | /// <summary> |
232 | /// Test that we do not attempt to attach an in-world object that someone else is sitting on. | 346 | /// Test that we do not attempt to attach an in-world object that someone else is sitting on. |
233 | /// </summary> | 347 | /// </summary> |
@@ -275,29 +389,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
275 | 389 | ||
276 | InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); | 390 | InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); |
277 | 391 | ||
278 | m_numberOfAttachEventsFired = 0; | 392 | { |
279 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( | 393 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( |
280 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | 394 | sp, attItem.ID, (uint)AttachmentPoint.Chest); |
281 | 395 | ||
282 | // Check scene presence status | 396 | // Check scene presence status |
283 | Assert.That(sp.HasAttachments(), Is.True); | 397 | Assert.That(sp.HasAttachments(), Is.True); |
284 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | 398 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
285 | Assert.That(attachments.Count, Is.EqualTo(1)); | 399 | Assert.That(attachments.Count, Is.EqualTo(1)); |
286 | SceneObjectGroup attSo = attachments[0]; | 400 | SceneObjectGroup attSo = attachments[0]; |
287 | Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); | 401 | Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); |
288 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); | 402 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); |
289 | Assert.That(attSo.IsAttachment); | 403 | Assert.That(attSo.IsAttachment); |
290 | Assert.That(attSo.UsesPhysics, Is.False); | 404 | Assert.That(attSo.UsesPhysics, Is.False); |
291 | Assert.That(attSo.IsTemporary, Is.False); | 405 | Assert.That(attSo.IsTemporary, Is.False); |
406 | |||
407 | // Check appearance status | ||
408 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
409 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | ||
410 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
411 | |||
412 | // Check events | ||
413 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
414 | } | ||
415 | |||
416 | // Test attaching an already attached attachment | ||
417 | { | ||
418 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( | ||
419 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | ||
292 | 420 | ||
293 | // Check appearance status | 421 | // Check scene presence status |
294 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | 422 | Assert.That(sp.HasAttachments(), Is.True); |
295 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | 423 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
424 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
425 | SceneObjectGroup attSo = attachments[0]; | ||
426 | Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); | ||
427 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); | ||
428 | Assert.That(attSo.IsAttachment); | ||
429 | Assert.That(attSo.UsesPhysics, Is.False); | ||
430 | Assert.That(attSo.IsTemporary, Is.False); | ||
431 | |||
432 | // Check appearance status | ||
433 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
434 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | ||
435 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
436 | |||
437 | // Check events | ||
438 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
439 | } | ||
440 | } | ||
296 | 441 | ||
297 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 442 | /// <summary> |
443 | /// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point | ||
444 | /// </summary> | ||
445 | [Test] | ||
446 | public void TestWearAttachmentFromInventory() | ||
447 | { | ||
448 | TestHelpers.InMethod(); | ||
449 | // TestHelpers.EnableLogging(); | ||
298 | 450 | ||
299 | // Check events | 451 | Scene scene = CreateTestScene(); |
300 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | 452 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); |
453 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); | ||
454 | |||
455 | InventoryItemBase attItem1 = CreateAttachmentItem(scene, ua1.PrincipalID, "att1", 0x10, 0x20); | ||
456 | InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21); | ||
457 | |||
458 | { | ||
459 | m_numberOfAttachEventsFired = 0; | ||
460 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default); | ||
461 | |||
462 | // default attachment point is currently the left hand. | ||
463 | Assert.That(sp.HasAttachments(), Is.True); | ||
464 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
465 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
466 | SceneObjectGroup attSo = attachments[0]; | ||
467 | Assert.That(attSo.Name, Is.EqualTo(attItem1.Name)); | ||
468 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
469 | Assert.That(attSo.IsAttachment); | ||
470 | |||
471 | // Check appearance status | ||
472 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
473 | Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
474 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
475 | |||
476 | // Check events | ||
477 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
478 | } | ||
479 | |||
480 | // Test wearing a second attachment at the same position | ||
481 | // Until multiple attachments at one point is implemented, this will remove the first attachment | ||
482 | // This test relies on both attachments having the same default attachment point (in this case LeftHand | ||
483 | // since none other has been set). | ||
484 | { | ||
485 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); | ||
486 | |||
487 | // default attachment point is currently the left hand. | ||
488 | Assert.That(sp.HasAttachments(), Is.True); | ||
489 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
490 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
491 | SceneObjectGroup attSo = attachments[0]; | ||
492 | Assert.That(attSo.Name, Is.EqualTo(attItem2.Name)); | ||
493 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
494 | Assert.That(attSo.IsAttachment); | ||
495 | |||
496 | // Check appearance status | ||
497 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
498 | Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
499 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
500 | |||
501 | // Check events | ||
502 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
503 | } | ||
504 | |||
505 | // Test wearing an already attached attachment | ||
506 | { | ||
507 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); | ||
508 | |||
509 | // default attachment point is currently the left hand. | ||
510 | Assert.That(sp.HasAttachments(), Is.True); | ||
511 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
512 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
513 | SceneObjectGroup attSo = attachments[0]; | ||
514 | Assert.That(attSo.Name, Is.EqualTo(attItem2.Name)); | ||
515 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
516 | Assert.That(attSo.IsAttachment); | ||
517 | |||
518 | // Check appearance status | ||
519 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
520 | Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
521 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
522 | |||
523 | // Check events | ||
524 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
525 | } | ||
301 | } | 526 | } |
302 | 527 | ||
303 | /// <summary> | 528 | /// <summary> |
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs index 37131b9..1f1568f 100644 --- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs | |||
@@ -39,7 +39,7 @@ using OpenSim.Region.Framework; | |||
39 | using OpenSim.Region.Framework.Interfaces; | 39 | using OpenSim.Region.Framework.Interfaces; |
40 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
41 | 41 | ||
42 | namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule | 42 | namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule |
43 | { | 43 | { |
44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] | 44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] |
45 | public class DAExampleModule : INonSharedRegionModule | 45 | public class DAExampleModule : INonSharedRegionModule |
@@ -48,6 +48,8 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule | |||
48 | 48 | ||
49 | private static readonly bool ENABLED = false; // enable for testing | 49 | private static readonly bool ENABLED = false; // enable for testing |
50 | 50 | ||
51 | public const string DANamespace = "DAExample Module"; | ||
52 | |||
51 | protected Scene m_scene; | 53 | protected Scene m_scene; |
52 | protected IDialogModule m_dialogMod; | 54 | protected IDialogModule m_dialogMod; |
53 | 55 | ||
@@ -85,19 +87,29 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule | |||
85 | { | 87 | { |
86 | OSDMap attrs = null; | 88 | OSDMap attrs = null; |
87 | SceneObjectPart sop = m_scene.GetSceneObjectPart(groupId); | 89 | SceneObjectPart sop = m_scene.GetSceneObjectPart(groupId); |
88 | if (!sop.DynAttrs.TryGetValue(Name, out attrs)) | 90 | |
91 | if (sop == null) | ||
92 | return true; | ||
93 | |||
94 | if (!sop.DynAttrs.TryGetValue(DANamespace, out attrs)) | ||
89 | attrs = new OSDMap(); | 95 | attrs = new OSDMap(); |
90 | 96 | ||
91 | OSDInteger newValue; | 97 | OSDInteger newValue; |
92 | |||
93 | if (!attrs.ContainsKey("moves")) | ||
94 | newValue = new OSDInteger(1); | ||
95 | else | ||
96 | newValue = new OSDInteger(((OSDInteger)attrs["moves"]).AsInteger() + 1); | ||
97 | |||
98 | attrs["moves"] = newValue; | ||
99 | 98 | ||
100 | sop.DynAttrs[Name] = attrs; | 99 | // We have to lock on the entire dynamic attributes map to avoid race conditions with serialization code. |
100 | lock (sop.DynAttrs) | ||
101 | { | ||
102 | if (!attrs.ContainsKey("moves")) | ||
103 | newValue = new OSDInteger(1); | ||
104 | else | ||
105 | newValue = new OSDInteger(attrs["moves"].AsInteger() + 1); | ||
106 | |||
107 | attrs["moves"] = newValue; | ||
108 | |||
109 | sop.DynAttrs[DANamespace] = attrs; | ||
110 | } | ||
111 | |||
112 | sop.ParentGroup.HasGroupChanged = true; | ||
101 | 113 | ||
102 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); | 114 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); |
103 | 115 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs new file mode 100644 index 0000000..650aa35 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs | |||
@@ -0,0 +1,139 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using log4net; | ||
32 | using Mono.Addins; | ||
33 | using Nini.Config; | ||
34 | using OpenMetaverse; | ||
35 | using OpenMetaverse.Packets; | ||
36 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Framework; | ||
39 | using OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule; | ||
40 | using OpenSim.Region.Framework.Interfaces; | ||
41 | using OpenSim.Region.Framework.Scenes; | ||
42 | |||
43 | namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule | ||
44 | { | ||
45 | /// <summary> | ||
46 | /// Example module for experimenting with and demonstrating dynamic object ideas. | ||
47 | /// </summary> | ||
48 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DOExampleModule")] | ||
49 | public class DOExampleModule : INonSharedRegionModule | ||
50 | { | ||
51 | public class MyObject | ||
52 | { | ||
53 | public int Moves { get; set; } | ||
54 | |||
55 | public MyObject(int moves) | ||
56 | { | ||
57 | Moves = moves; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
62 | |||
63 | private static readonly bool ENABLED = false; // enable for testing | ||
64 | |||
65 | private Scene m_scene; | ||
66 | private IDialogModule m_dialogMod; | ||
67 | |||
68 | public string Name { get { return "DOExample Module"; } } | ||
69 | public Type ReplaceableInterface { get { return null; } } | ||
70 | |||
71 | public void Initialise(IConfigSource source) {} | ||
72 | |||
73 | public void AddRegion(Scene scene) | ||
74 | { | ||
75 | if (ENABLED) | ||
76 | { | ||
77 | m_scene = scene; | ||
78 | m_scene.EventManager.OnObjectAddedToScene += OnObjectAddedToScene; | ||
79 | m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; | ||
80 | m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | public void RemoveRegion(Scene scene) | ||
85 | { | ||
86 | if (ENABLED) | ||
87 | { | ||
88 | m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | public void RegionLoaded(Scene scene) {} | ||
93 | |||
94 | public void Close() | ||
95 | { | ||
96 | RemoveRegion(m_scene); | ||
97 | } | ||
98 | |||
99 | private void OnObjectAddedToScene(SceneObjectGroup so) | ||
100 | { | ||
101 | SceneObjectPart rootPart = so.RootPart; | ||
102 | |||
103 | OSDMap attrs; | ||
104 | |||
105 | int movesSoFar = 0; | ||
106 | |||
107 | // Console.WriteLine("Here for {0}", so.Name); | ||
108 | |||
109 | if (rootPart.DynAttrs.TryGetValue(DAExampleModule.DANamespace, out attrs)) | ||
110 | { | ||
111 | movesSoFar = attrs["moves"].AsInteger(); | ||
112 | |||
113 | m_log.DebugFormat( | ||
114 | "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name); | ||
115 | } | ||
116 | |||
117 | rootPart.DynObjs.Add(Name, new MyObject(movesSoFar)); | ||
118 | } | ||
119 | |||
120 | private bool OnSceneGroupMove(UUID groupId, Vector3 delta) | ||
121 | { | ||
122 | SceneObjectGroup so = m_scene.GetSceneObjectGroup(groupId); | ||
123 | |||
124 | if (so == null) | ||
125 | return true; | ||
126 | |||
127 | object rawObj = so.RootPart.DynObjs.Get(Name); | ||
128 | |||
129 | if (rawObj != null) | ||
130 | { | ||
131 | MyObject myObj = (MyObject)rawObj; | ||
132 | |||
133 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", so.Name, so.UUID, ++myObj.Moves)); | ||
134 | } | ||
135 | |||
136 | return true; | ||
137 | } | ||
138 | } | ||
139 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 07c3666..9b1b69a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -66,6 +66,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
66 | /// </summary> | 66 | /// </summary> |
67 | public bool WaitForAgentArrivedAtDestination { get; set; } | 67 | public bool WaitForAgentArrivedAtDestination { get; set; } |
68 | 68 | ||
69 | /// <summary> | ||
70 | /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests. | ||
71 | /// </summary> | ||
72 | /// <remarks> | ||
73 | /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a | ||
74 | /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the | ||
75 | /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport | ||
76 | /// cancellation consistently suceed. | ||
77 | /// </remarks> | ||
78 | public bool DisableInterRegionTeleportCancellation { get; set; } | ||
79 | |||
69 | protected bool m_Enabled = false; | 80 | protected bool m_Enabled = false; |
70 | 81 | ||
71 | public Scene Scene { get; private set; } | 82 | public Scene Scene { get; private set; } |
@@ -116,6 +127,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
116 | IConfig transferConfig = source.Configs["EntityTransfer"]; | 127 | IConfig transferConfig = source.Configs["EntityTransfer"]; |
117 | if (transferConfig != null) | 128 | if (transferConfig != null) |
118 | { | 129 | { |
130 | DisableInterRegionTeleportCancellation | ||
131 | = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); | ||
132 | |||
119 | WaitForAgentArrivedAtDestination | 133 | WaitForAgentArrivedAtDestination |
120 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); | 134 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); |
121 | 135 | ||
@@ -150,6 +164,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
150 | { | 164 | { |
151 | client.OnTeleportHomeRequest += TeleportHome; | 165 | client.OnTeleportHomeRequest += TeleportHome; |
152 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; | 166 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; |
167 | |||
168 | if (!DisableInterRegionTeleportCancellation) | ||
169 | client.OnTeleportCancel += OnClientCancelTeleport; | ||
153 | } | 170 | } |
154 | 171 | ||
155 | public virtual void Close() {} | 172 | public virtual void Close() {} |
@@ -168,6 +185,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
168 | 185 | ||
169 | #region Agent Teleports | 186 | #region Agent Teleports |
170 | 187 | ||
188 | private void OnClientCancelTeleport(IClientAPI client) | ||
189 | { | ||
190 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); | ||
191 | |||
192 | m_log.DebugFormat( | ||
193 | "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name); | ||
194 | } | ||
195 | |||
171 | public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) | 196 | public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) |
172 | { | 197 | { |
173 | if (sp.Scene.Permissions.IsGridGod(sp.UUID)) | 198 | if (sp.Scene.Permissions.IsGridGod(sp.UUID)) |
@@ -519,6 +544,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
519 | if (sp.ParentID != (uint)0) | 544 | if (sp.ParentID != (uint)0) |
520 | sp.StandUp(); | 545 | sp.StandUp(); |
521 | 546 | ||
547 | if (DisableInterRegionTeleportCancellation) | ||
548 | teleportFlags |= (uint)TeleportFlags.DisableCancel; | ||
549 | |||
522 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to | 550 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to |
523 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). | 551 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). |
524 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 552 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
@@ -567,6 +595,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
567 | return; | 595 | return; |
568 | } | 596 | } |
569 | 597 | ||
598 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) | ||
599 | { | ||
600 | m_log.DebugFormat( | ||
601 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", | ||
602 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
603 | |||
604 | return; | ||
605 | } | ||
606 | |||
570 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | 607 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. |
571 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 608 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
572 | 609 | ||
@@ -631,7 +668,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
631 | return; | 668 | return; |
632 | } | 669 | } |
633 | 670 | ||
634 | sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); | 671 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) |
672 | { | ||
673 | m_log.DebugFormat( | ||
674 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", | ||
675 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
676 | |||
677 | CleanupAbortedInterRegionTeleport(sp, finalDestination); | ||
678 | |||
679 | return; | ||
680 | } | ||
635 | 681 | ||
636 | m_log.DebugFormat( | 682 | m_log.DebugFormat( |
637 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", | 683 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", |
@@ -714,14 +760,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
714 | // } | 760 | // } |
715 | } | 761 | } |
716 | 762 | ||
717 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) | 763 | /// <summary> |
764 | /// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation. | ||
765 | /// </summary> | ||
766 | /// <remarks> | ||
767 | /// All operations here must be idempotent so that we can call this method at any point in the teleport process | ||
768 | /// up until we send the TeleportFinish event quene event to the viewer. | ||
769 | /// <remarks> | ||
770 | /// <param name='sp'> </param> | ||
771 | /// <param name='finalDestination'></param> | ||
772 | protected virtual void CleanupAbortedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) | ||
718 | { | 773 | { |
719 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 774 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
720 | 775 | ||
721 | // Client never contacted destination. Let's restore everything back | ||
722 | sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); | ||
723 | |||
724 | // Fail. Reset it back | ||
725 | sp.IsChildAgent = false; | 776 | sp.IsChildAgent = false; |
726 | ReInstantiateScripts(sp); | 777 | ReInstantiateScripts(sp); |
727 | 778 | ||
@@ -729,7 +780,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
729 | 780 | ||
730 | // Finally, kill the agent we just created at the destination. | 781 | // Finally, kill the agent we just created at the destination. |
731 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); | 782 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); |
783 | } | ||
732 | 784 | ||
785 | /// <summary> | ||
786 | /// Signal that the inter-region teleport failed and perform cleanup. | ||
787 | /// </summary> | ||
788 | /// <param name='sp'></param> | ||
789 | /// <param name='finalDestination'></param> | ||
790 | /// <param name='logout'></param> | ||
791 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) | ||
792 | { | ||
793 | CleanupAbortedInterRegionTeleport(sp, finalDestination); | ||
794 | |||
795 | sp.ControllingClient.SendTeleportFailed( | ||
796 | string.Format("Problems connecting to destination {0}", finalDestination.RegionName)); | ||
733 | sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); | 797 | sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); |
734 | } | 798 | } |
735 | 799 | ||
@@ -1206,6 +1270,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1206 | // region doesn't take it | 1270 | // region doesn't take it |
1207 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | 1271 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
1208 | 1272 | ||
1273 | m_log.WarnFormat( | ||
1274 | "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.", | ||
1275 | neighbourRegion.RegionName, agent.Name); | ||
1276 | |||
1209 | ReInstantiateScripts(agent); | 1277 | ReInstantiateScripts(agent); |
1210 | agent.AddToPhysicalScene(isFlying); | 1278 | agent.AddToPhysicalScene(isFlying); |
1211 | 1279 | ||
@@ -1225,6 +1293,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1225 | neighbourRegion.RegionHandle); | 1293 | neighbourRegion.RegionHandle); |
1226 | return agent; | 1294 | return agent; |
1227 | } | 1295 | } |
1296 | |||
1228 | // No turning back | 1297 | // No turning back |
1229 | agent.IsChildAgent = true; | 1298 | agent.IsChildAgent = true; |
1230 | 1299 | ||
@@ -2092,7 +2161,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2092 | 2161 | ||
2093 | public bool IsInTransit(UUID id) | 2162 | public bool IsInTransit(UUID id) |
2094 | { | 2163 | { |
2095 | return m_entityTransferStateMachine.IsInTransit(id); | 2164 | return m_entityTransferStateMachine.GetAgentTransferState(id) != null; |
2096 | } | 2165 | } |
2097 | 2166 | ||
2098 | protected void ReInstantiateScripts(ScenePresence sp) | 2167 | protected void ReInstantiateScripts(ScenePresence sp) |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs index d0cab49..24d81d9 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs | |||
@@ -51,8 +51,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
51 | /// This is a state machine. | 51 | /// This is a state machine. |
52 | /// | 52 | /// |
53 | /// [Entry] => Preparing | 53 | /// [Entry] => Preparing |
54 | /// Preparing => { Transferring || CleaningUp || [Exit] } | 54 | /// Preparing => { Transferring || Cancelling || CleaningUp || [Exit] } |
55 | /// Transferring => { ReceivedAtDestination || CleaningUp } | 55 | /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp } |
56 | /// Cancelling => CleaningUp | ||
56 | /// ReceivedAtDestination => CleaningUp | 57 | /// ReceivedAtDestination => CleaningUp |
57 | /// CleaningUp => [Exit] | 58 | /// CleaningUp => [Exit] |
58 | /// | 59 | /// |
@@ -64,7 +65,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
64 | Preparing, // The agent is being prepared for transfer | 65 | Preparing, // The agent is being prepared for transfer |
65 | Transferring, // The agent is in the process of being transferred to a destination | 66 | Transferring, // The agent is in the process of being transferred to a destination |
66 | ReceivedAtDestination, // The destination has notified us that the agent has been successfully received | 67 | ReceivedAtDestination, // The destination has notified us that the agent has been successfully received |
67 | CleaningUp // The agent is being changed to child/removed after a transfer | 68 | CleaningUp, // The agent is being changed to child/removed after a transfer |
69 | Cancelling // The user has cancelled the teleport but we have yet to act upon this. | ||
68 | } | 70 | } |
69 | 71 | ||
70 | /// <summary> | 72 | /// <summary> |
@@ -115,42 +117,110 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
115 | /// <param name='newState'></param> | 117 | /// <param name='newState'></param> |
116 | /// <returns></returns> | 118 | /// <returns></returns> |
117 | /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> | 119 | /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> |
118 | internal void UpdateInTransit(UUID id, AgentTransferState newState) | 120 | internal bool UpdateInTransit(UUID id, AgentTransferState newState) |
119 | { | 121 | { |
122 | bool transitionOkay = false; | ||
123 | |||
124 | // We don't want to throw an exception on cancel since this can come it at any time. | ||
125 | bool failIfNotOkay = true; | ||
126 | |||
127 | // Should be a failure message if failure is not okay. | ||
128 | string failureMessage = null; | ||
129 | |||
130 | AgentTransferState? oldState = null; | ||
131 | |||
120 | lock (m_agentsInTransit) | 132 | lock (m_agentsInTransit) |
121 | { | 133 | { |
122 | // Illegal to try and update an agent that's not actually in transit. | 134 | // Illegal to try and update an agent that's not actually in transit. |
123 | if (!m_agentsInTransit.ContainsKey(id)) | 135 | if (!m_agentsInTransit.ContainsKey(id)) |
124 | throw new Exception( | 136 | { |
125 | string.Format( | 137 | if (newState != AgentTransferState.Cancelling) |
126 | "Agent with ID {0} is not registered as in transit in {1}", | 138 | failureMessage = string.Format( |
127 | id, m_mod.Scene.RegionInfo.RegionName)); | 139 | "Agent with ID {0} is not registered as in transit in {1}", |
128 | 140 | id, m_mod.Scene.RegionInfo.RegionName); | |
129 | AgentTransferState oldState = m_agentsInTransit[id]; | 141 | else |
142 | failIfNotOkay = false; | ||
143 | } | ||
144 | else | ||
145 | { | ||
146 | oldState = m_agentsInTransit[id]; | ||
130 | 147 | ||
131 | bool transitionOkay = false; | 148 | if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) |
149 | { | ||
150 | transitionOkay = true; | ||
151 | } | ||
152 | else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing) | ||
153 | { | ||
154 | transitionOkay = true; | ||
155 | } | ||
156 | else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring) | ||
157 | { | ||
158 | transitionOkay = true; | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | if (newState == AgentTransferState.Cancelling | ||
163 | && (oldState == AgentTransferState.Preparing || oldState == AgentTransferState.Transferring)) | ||
164 | { | ||
165 | transitionOkay = true; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | failIfNotOkay = false; | ||
170 | } | ||
171 | } | ||
132 | 172 | ||
133 | if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | 173 | if (!transitionOkay) |
134 | transitionOkay = true; | 174 | failureMessage |
135 | else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing) | 175 | = string.Format( |
136 | transitionOkay = true; | 176 | "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", |
137 | else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring) | 177 | id, oldState, newState, m_mod.Scene.RegionInfo.RegionName); |
138 | transitionOkay = true; | 178 | } |
139 | 179 | ||
140 | if (transitionOkay) | 180 | if (transitionOkay) |
181 | { | ||
141 | m_agentsInTransit[id] = newState; | 182 | m_agentsInTransit[id] = newState; |
142 | else | 183 | |
143 | throw new Exception( | 184 | // m_log.DebugFormat( |
144 | string.Format( | 185 | // "[ENTITY TRANSFER STATE MACHINE]: Changed agent with id {0} from state {1} to {2} in {3}", |
145 | "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", | 186 | // id, oldState, newState, m_mod.Scene.Name); |
146 | id, oldState, newState, m_mod.Scene.RegionInfo.RegionName)); | 187 | } |
188 | else if (failIfNotOkay) | ||
189 | { | ||
190 | throw new Exception(failureMessage); | ||
191 | } | ||
192 | // else | ||
193 | // { | ||
194 | // if (oldState != null) | ||
195 | // m_log.DebugFormat( | ||
196 | // "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} from state {1} to {2} in {3}", | ||
197 | // id, oldState, newState, m_mod.Scene.Name); | ||
198 | // else | ||
199 | // m_log.DebugFormat( | ||
200 | // "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} to state {1} in {2} since agent not in transit", | ||
201 | // id, newState, m_mod.Scene.Name); | ||
202 | // } | ||
147 | } | 203 | } |
204 | |||
205 | return transitionOkay; | ||
148 | } | 206 | } |
149 | 207 | ||
150 | internal bool IsInTransit(UUID id) | 208 | /// <summary> |
209 | /// Gets the current agent transfer state. | ||
210 | /// </summary> | ||
211 | /// <returns>Null if the agent is not in transit</returns> | ||
212 | /// <param name='id'> | ||
213 | /// Identifier. | ||
214 | /// </param> | ||
215 | internal AgentTransferState? GetAgentTransferState(UUID id) | ||
151 | { | 216 | { |
152 | lock (m_agentsInTransit) | 217 | lock (m_agentsInTransit) |
153 | return m_agentsInTransit.ContainsKey(id); | 218 | { |
219 | if (!m_agentsInTransit.ContainsKey(id)) | ||
220 | return null; | ||
221 | else | ||
222 | return m_agentsInTransit[id]; | ||
223 | } | ||
154 | } | 224 | } |
155 | 225 | ||
156 | /// <summary> | 226 | /// <summary> |
@@ -203,14 +273,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
203 | 273 | ||
204 | lock (m_agentsInTransit) | 274 | lock (m_agentsInTransit) |
205 | { | 275 | { |
206 | if (!IsInTransit(id)) | 276 | AgentTransferState? currentState = GetAgentTransferState(id); |
277 | |||
278 | if (currentState == null) | ||
207 | throw new Exception( | 279 | throw new Exception( |
208 | string.Format( | 280 | string.Format( |
209 | "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit", | 281 | "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit", |
210 | id, m_mod.Scene.RegionInfo.RegionName)); | 282 | id, m_mod.Scene.RegionInfo.RegionName)); |
211 | 283 | ||
212 | AgentTransferState currentState = m_agentsInTransit[id]; | ||
213 | |||
214 | if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination) | 284 | if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination) |
215 | throw new Exception( | 285 | throw new Exception( |
216 | string.Format( | 286 | string.Format( |
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index 4c9ee06..64feec1 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | |||
@@ -414,8 +414,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
414 | } | 414 | } |
415 | private void RegisterStatsManagerRegionStatistics() | 415 | private void RegisterStatsManagerRegionStatistics() |
416 | { | 416 | { |
417 | string regionName = m_scene.RegionInfo.RegionName; | ||
418 | |||
419 | MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); }); | 417 | MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); }); |
420 | MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); }); | 418 | MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); }); |
421 | MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); }); | 419 | MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); }); |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index f04fabe..4cecd85 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -516,6 +516,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
516 | foreach (string line in GetLines(data, dataDelim)) | 516 | foreach (string line in GetLines(data, dataDelim)) |
517 | { | 517 | { |
518 | string nextLine = line.Trim(); | 518 | string nextLine = line.Trim(); |
519 | |||
520 | // m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine); | ||
521 | |||
519 | //replace with switch, or even better, do some proper parsing | 522 | //replace with switch, or even better, do some proper parsing |
520 | if (nextLine.StartsWith("MoveTo")) | 523 | if (nextLine.StartsWith("MoveTo")) |
521 | { | 524 | { |
@@ -829,6 +832,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
829 | float y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); | 832 | float y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); |
830 | PointF point = new PointF(x, y); | 833 | PointF point = new PointF(x, y); |
831 | points[i / 2] = point; | 834 | points[i / 2] = point; |
835 | |||
836 | // m_log.DebugFormat("[VECTOR RENDER MODULE]: Got point {0}", points[i / 2]); | ||
832 | } | 837 | } |
833 | } | 838 | } |
834 | } | 839 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 3c18074..a413546 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs | |||
@@ -219,12 +219,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
219 | { | 219 | { |
220 | // m_log.DebugFormat( | 220 | // m_log.DebugFormat( |
221 | // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", | 221 | // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", |
222 | // s.RegionInfo.RegionName, destination.RegionHandle); | 222 | // destination.RegionName, destination.RegionID); |
223 | 223 | ||
224 | return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); | 224 | return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); |
225 | } | 225 | } |
226 | 226 | ||
227 | // m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle); | 227 | // m_log.DebugFormat( |
228 | // "[LOCAL COMMS]: Did not find region {0} {1} for ChildAgentUpdate", | ||
229 | // destination.RegionName, destination.RegionID); | ||
230 | |||
228 | return false; | 231 | return false; |
229 | } | 232 | } |
230 | 233 | ||
@@ -239,7 +242,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
239 | // note that we really don't need the GridRegion for this call | 242 | // note that we really don't need the GridRegion for this call |
240 | foreach (Scene s in m_scenes.Values) | 243 | foreach (Scene s in m_scenes.Values) |
241 | { | 244 | { |
242 | //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); | 245 | // m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); |
243 | s.IncomingChildAgentDataUpdate(cAgentData); | 246 | s.IncomingChildAgentDataUpdate(cAgentData); |
244 | } | 247 | } |
245 | 248 | ||
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs index 7fc358d..73c592d 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs | |||
@@ -95,6 +95,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
95 | return null; | 95 | return null; |
96 | } | 96 | } |
97 | 97 | ||
98 | public ILandObject GetLandObject(Vector3 position) | ||
99 | { | ||
100 | return GetLandObject(position.X, position.Y); | ||
101 | } | ||
102 | |||
98 | public ILandObject GetLandObject(int x, int y) | 103 | public ILandObject GetLandObject(int x, int y) |
99 | { | 104 | { |
100 | if (m_landManagementModule != null) | 105 | if (m_landManagementModule != null) |
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs index 345f01b..b67312e 100644 --- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs | |||
@@ -41,6 +41,16 @@ namespace OpenSim.Region.Framework.Interfaces | |||
41 | Value = 3 | 41 | Value = 3 |
42 | } | 42 | } |
43 | 43 | ||
44 | public enum JsonStoreValueType | ||
45 | { | ||
46 | Undefined = 0, | ||
47 | Boolean = 1, | ||
48 | Integer = 2, | ||
49 | Float = 3, | ||
50 | String = 4, | ||
51 | UUID = 5 | ||
52 | } | ||
53 | |||
44 | public delegate void TakeValueCallback(string s); | 54 | public delegate void TakeValueCallback(string s); |
45 | 55 | ||
46 | public interface IJsonStoreModule | 56 | public interface IJsonStoreModule |
@@ -49,7 +59,9 @@ namespace OpenSim.Region.Framework.Interfaces | |||
49 | bool CreateStore(string value, ref UUID result); | 59 | bool CreateStore(string value, ref UUID result); |
50 | bool DestroyStore(UUID storeID); | 60 | bool DestroyStore(UUID storeID); |
51 | 61 | ||
52 | JsonStoreNodeType GetPathType(UUID storeID, string path); | 62 | JsonStoreNodeType GetNodeType(UUID storeID, string path); |
63 | JsonStoreValueType GetValueType(UUID storeID, string path); | ||
64 | |||
53 | bool TestStore(UUID storeID); | 65 | bool TestStore(UUID storeID); |
54 | 66 | ||
55 | bool SetValue(UUID storeID, string path, string value, bool useJson); | 67 | bool SetValue(UUID storeID, string path, string value, bool useJson); |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cce8b21..a8b63fe 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -129,6 +129,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
129 | /// Dynamic attributes can be created and deleted as required. | 129 | /// Dynamic attributes can be created and deleted as required. |
130 | /// </summary> | 130 | /// </summary> |
131 | public DAMap DynAttrs { get; set; } | 131 | public DAMap DynAttrs { get; set; } |
132 | |||
133 | private DOMap m_dynObjs; | ||
134 | |||
135 | /// <summary> | ||
136 | /// Dynamic objects that can be created and deleted as required. | ||
137 | /// </summary> | ||
138 | public DOMap DynObjs | ||
139 | { | ||
140 | get | ||
141 | { | ||
142 | if (m_dynObjs == null) | ||
143 | m_dynObjs = new DOMap(); | ||
144 | |||
145 | return m_dynObjs; | ||
146 | } | ||
147 | |||
148 | set | ||
149 | { | ||
150 | m_dynObjs = value; | ||
151 | } | ||
152 | } | ||
132 | 153 | ||
133 | /// <value> | 154 | /// <value> |
134 | /// Is this a root part? | 155 | /// Is this a root part? |
@@ -4503,8 +4524,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
4503 | 4524 | ||
4504 | Changed changeFlags = 0; | 4525 | Changed changeFlags = 0; |
4505 | 4526 | ||
4527 | Primitive.TextureEntryFace fallbackNewFace = newTex.DefaultTexture; | ||
4528 | Primitive.TextureEntryFace fallbackOldFace = oldTex.DefaultTexture; | ||
4529 | |||
4530 | // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all | ||
4531 | // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point. | ||
4532 | if (fallbackNewFace == null) | ||
4533 | { | ||
4534 | fallbackNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); | ||
4535 | newTex.DefaultTexture = fallbackNewFace; | ||
4536 | } | ||
4537 | if (fallbackOldFace == null) | ||
4538 | { | ||
4539 | fallbackOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); | ||
4540 | oldTex.DefaultTexture = fallbackOldFace; | ||
4541 | } | ||
4542 | |||
4506 | for (int i = 0 ; i < GetNumberOfSides(); i++) | 4543 | for (int i = 0 ; i < GetNumberOfSides(); i++) |
4507 | { | 4544 | { |
4545 | |||
4508 | Primitive.TextureEntryFace newFace = newTex.DefaultTexture; | 4546 | Primitive.TextureEntryFace newFace = newTex.DefaultTexture; |
4509 | Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture; | 4547 | Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture; |
4510 | 4548 | ||
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 39a885c..82bb759 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -559,16 +559,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
559 | 559 | ||
560 | private Quaternion m_bodyRot = Quaternion.Identity; | 560 | private Quaternion m_bodyRot = Quaternion.Identity; |
561 | 561 | ||
562 | /// <summary> | ||
563 | /// The rotation of the avatar. | ||
564 | /// </summary> | ||
565 | /// <remarks> | ||
566 | /// If the avatar is not sitting, this is with respect to the world | ||
567 | /// If the avatar is sitting, this is a with respect to the part that it's sitting upon (a local rotation). | ||
568 | /// If you always want the world rotation, use GetWorldRotation() | ||
569 | /// </remarks> | ||
562 | public Quaternion Rotation | 570 | public Quaternion Rotation |
563 | { | 571 | { |
564 | get { return m_bodyRot; } | 572 | get |
573 | { | ||
574 | return m_bodyRot; | ||
575 | } | ||
576 | |||
565 | set | 577 | set |
566 | { | 578 | { |
567 | m_bodyRot = value; | 579 | m_bodyRot = value; |
580 | |||
568 | if (PhysicsActor != null) | 581 | if (PhysicsActor != null) |
569 | { | ||
570 | PhysicsActor.Orientation = m_bodyRot; | 582 | PhysicsActor.Orientation = m_bodyRot; |
571 | } | 583 | |
572 | // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); | 584 | // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); |
573 | } | 585 | } |
574 | } | 586 | } |
@@ -608,6 +620,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
608 | set { m_health = value; } | 620 | set { m_health = value; } |
609 | } | 621 | } |
610 | 622 | ||
623 | /// <summary> | ||
624 | /// Gets the world rotation of this presence. | ||
625 | /// </summary> | ||
626 | /// <remarks> | ||
627 | /// Unlike Rotation, this returns the world rotation no matter whether the avatar is sitting on a prim or not. | ||
628 | /// </remarks> | ||
629 | /// <returns></returns> | ||
630 | public Quaternion GetWorldRotation() | ||
631 | { | ||
632 | if (IsSatOnObject) | ||
633 | { | ||
634 | SceneObjectPart sitPart = ParentPart; | ||
635 | |||
636 | if (sitPart != null) | ||
637 | return sitPart.GetWorldRotation() * Rotation; | ||
638 | } | ||
639 | |||
640 | return Rotation; | ||
641 | } | ||
642 | |||
611 | public void AdjustKnownSeeds() | 643 | public void AdjustKnownSeeds() |
612 | { | 644 | { |
613 | Dictionary<ulong, string> seeds; | 645 | Dictionary<ulong, string> seeds; |
@@ -709,8 +741,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
709 | 741 | ||
710 | #endregion | 742 | #endregion |
711 | 743 | ||
712 | |||
713 | |||
714 | #region Constructor(s) | 744 | #region Constructor(s) |
715 | 745 | ||
716 | public ScenePresence( | 746 | public ScenePresence( |
@@ -1613,32 +1643,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
1613 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | 1643 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || |
1614 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | 1644 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); |
1615 | 1645 | ||
1616 | |||
1617 | //m_log.Debug("[CONTROL]: " +flags); | 1646 | //m_log.Debug("[CONTROL]: " +flags); |
1618 | // Applies a satisfying roll effect to the avatar when flying. | 1647 | // Applies a satisfying roll effect to the avatar when flying. |
1619 | if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)) | 1648 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) |
1620 | { | 1649 | { |
1621 | 1650 | ApplyFlyingRoll( | |
1622 | ApplyFlyingRoll(FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0)); | 1651 | FLY_ROLL_RADIANS_PER_UPDATE, |
1623 | 1652 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | |
1624 | 1653 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | |
1625 | } | 1654 | } |
1626 | else if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0) && | 1655 | else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && |
1627 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)) | 1656 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) |
1628 | { | 1657 | { |
1629 | ApplyFlyingRoll(-FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0)); | 1658 | ApplyFlyingRoll( |
1630 | 1659 | -FLY_ROLL_RADIANS_PER_UPDATE, | |
1631 | 1660 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, | |
1661 | (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||
1632 | } | 1662 | } |
1633 | else | 1663 | else |
1634 | { | 1664 | { |
1635 | if (m_AngularVelocity.Z != 0) | 1665 | if (m_AngularVelocity.Z != 0) |
1636 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | 1666 | m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); |
1637 | 1667 | } | |
1638 | } | ||
1639 | |||
1640 | |||
1641 | |||
1642 | 1668 | ||
1643 | if (Flying && IsColliding && controlland) | 1669 | if (Flying && IsColliding && controlland) |
1644 | { | 1670 | { |
@@ -2400,7 +2426,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2400 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> | 2426 | /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> |
2401 | public void AddNewMovement(Vector3 vec) | 2427 | public void AddNewMovement(Vector3 vec) |
2402 | { | 2428 | { |
2403 | // m_log.DebugFormat("[SCENE PRESENCE]: Adding new movement {0} for {1}", vec, Name); | 2429 | // m_log.DebugFormat( |
2430 | // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); | ||
2404 | 2431 | ||
2405 | Vector3 direc = vec * Rotation; | 2432 | Vector3 direc = vec * Rotation; |
2406 | direc.Normalize(); | 2433 | direc.Normalize(); |
@@ -2420,6 +2447,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2420 | 2447 | ||
2421 | direc *= 0.03f * 128f * SpeedModifier; | 2448 | direc *= 0.03f * 128f * SpeedModifier; |
2422 | 2449 | ||
2450 | // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); | ||
2451 | |||
2423 | if (PhysicsActor != null) | 2452 | if (PhysicsActor != null) |
2424 | { | 2453 | { |
2425 | if (Flying) | 2454 | if (Flying) |
@@ -2453,6 +2482,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2453 | } | 2482 | } |
2454 | } | 2483 | } |
2455 | 2484 | ||
2485 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); | ||
2486 | |||
2456 | // TODO: Add the force instead of only setting it to support multiple forces per frame? | 2487 | // TODO: Add the force instead of only setting it to support multiple forces per frame? |
2457 | m_forceToApply = direc; | 2488 | m_forceToApply = direc; |
2458 | } | 2489 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs index 96973de..4883ae7 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs | |||
@@ -110,8 +110,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
110 | 110 | ||
111 | Vector3 firstSize = new Vector3(2, 3, 4); | 111 | Vector3 firstSize = new Vector3(2, 3, 4); |
112 | Vector3 secondSize = new Vector3(5, 6, 7); | 112 | Vector3 secondSize = new Vector3(5, 6, 7); |
113 | Vector3 thirdSize = new Vector3(8, 9, 10); | 113 | // Vector3 thirdSize = new Vector3(8, 9, 10); |
114 | Vector3 fourthSize = new Vector3(11, 12, 13); | 114 | // Vector3 fourthSize = new Vector3(11, 12, 13); |
115 | 115 | ||
116 | Scene scene = new SceneHelpers().SetupScene(); | 116 | Scene scene = new SceneHelpers().SetupScene(); |
117 | scene.MaxUndoCount = 20; | 117 | scene.MaxUndoCount = 20; |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5faf131..bbfbbfc 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs | |||
@@ -289,108 +289,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
289 | // | 289 | // |
290 | // Assert.That(presence, Is.Null, "presence is not null"); | 290 | // Assert.That(presence, Is.Null, "presence is not null"); |
291 | // } | 291 | // } |
292 | |||
293 | // I'm commenting this test because it does not represent | ||
294 | // crossings. The Thread.Sleep's in here are not meaningful mocks, | ||
295 | // and they sometimes fail in panda. | ||
296 | // We need to talk in order to develop a test | ||
297 | // that really tests region crossings. There are 3 async components, | ||
298 | // but things are synchronous among them. So there should be | ||
299 | // 3 threads in here. | ||
300 | //[Test] | ||
301 | // public void T021_TestCrossToNewRegion() | ||
302 | // { | ||
303 | // TestHelpers.InMethod(); | ||
304 | // | ||
305 | // scene.RegisterRegionWithGrid(); | ||
306 | // scene2.RegisterRegionWithGrid(); | ||
307 | // | ||
308 | // // Adding child agent to region 1001 | ||
309 | // string reason; | ||
310 | // scene2.NewUserConnection(acd1,0, out reason); | ||
311 | // scene2.AddNewClient(testclient, PresenceType.User); | ||
312 | // | ||
313 | // ScenePresence presence = scene.GetScenePresence(agent1); | ||
314 | // presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); | ||
315 | // | ||
316 | // ScenePresence presence2 = scene2.GetScenePresence(agent1); | ||
317 | // | ||
318 | // // Adding neighbour region caps info to presence2 | ||
319 | // | ||
320 | // string cap = presence.ControllingClient.RequestClientInfo().CapsPath; | ||
321 | // presence2.AddNeighbourRegion(region1, cap); | ||
322 | // | ||
323 | // Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); | ||
324 | // Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); | ||
325 | // | ||
326 | // // Cross to x+1 | ||
327 | // presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); | ||
328 | // presence.Update(); | ||
329 | // | ||
330 | // EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); | ||
331 | // | ||
332 | // // Mimicking communication between client and server, by waiting OK from client | ||
333 | // // sent by TestClient.CrossRegion call. Originally, this is network comm. | ||
334 | // if (!wh.WaitOne(5000,false)) | ||
335 | // { | ||
336 | // presence.Update(); | ||
337 | // if (!wh.WaitOne(8000,false)) | ||
338 | // throw new ArgumentException("1 - Timeout waiting for signal/variable."); | ||
339 | // } | ||
340 | // | ||
341 | // // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which | ||
342 | // // would normally be fired after receiving the reply packet from comm. done on the last line. | ||
343 | // testclient.CompleteMovement(); | ||
344 | // | ||
345 | // // Crossings are asynchronous | ||
346 | // int timer = 10; | ||
347 | // | ||
348 | // // Make sure cross hasn't already finished | ||
349 | // if (!presence.IsInTransit && !presence.IsChildAgent) | ||
350 | // { | ||
351 | // // If not and not in transit yet, give it some more time | ||
352 | // Thread.Sleep(5000); | ||
353 | // } | ||
354 | // | ||
355 | // // Enough time, should at least be in transit by now. | ||
356 | // while (presence.IsInTransit && timer > 0) | ||
357 | // { | ||
358 | // Thread.Sleep(1000); | ||
359 | // timer-=1; | ||
360 | // } | ||
361 | // | ||
362 | // Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); | ||
363 | // Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); | ||
364 | // Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); | ||
365 | // | ||
366 | // // Cross Back | ||
367 | // presence2.AbsolutePosition = new Vector3(-10, 3, 100); | ||
368 | // presence2.Update(); | ||
369 | // | ||
370 | // if (!wh.WaitOne(5000,false)) | ||
371 | // { | ||
372 | // presence2.Update(); | ||
373 | // if (!wh.WaitOne(8000,false)) | ||
374 | // throw new ArgumentException("2 - Timeout waiting for signal/variable."); | ||
375 | // } | ||
376 | // testclient.CompleteMovement(); | ||
377 | // | ||
378 | // if (!presence2.IsInTransit && !presence2.IsChildAgent) | ||
379 | // { | ||
380 | // // If not and not in transit yet, give it some more time | ||
381 | // Thread.Sleep(5000); | ||
382 | // } | ||
383 | // | ||
384 | // // Enough time, should at least be in transit by now. | ||
385 | // while (presence2.IsInTransit && timer > 0) | ||
386 | // { | ||
387 | // Thread.Sleep(1000); | ||
388 | // timer-=1; | ||
389 | // } | ||
390 | // | ||
391 | // Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); | ||
392 | // Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); | ||
393 | // Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); | ||
394 | // } | ||
395 | } | 292 | } |
396 | } \ No newline at end of file | 293 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs new file mode 100644 index 0000000..81a2fcc --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs | |||
@@ -0,0 +1,157 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using Nini.Config; | ||
32 | using NUnit.Framework; | ||
33 | using OpenMetaverse; | ||
34 | using OpenSim.Framework; | ||
35 | using OpenSim.Framework.Communications; | ||
36 | using OpenSim.Framework.Servers; | ||
37 | using OpenSim.Region.Framework.Interfaces; | ||
38 | using OpenSim.Region.CoreModules.Framework; | ||
39 | using OpenSim.Region.CoreModules.Framework.EntityTransfer; | ||
40 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | ||
41 | using OpenSim.Tests.Common; | ||
42 | using OpenSim.Tests.Common.Mock; | ||
43 | |||
44 | namespace OpenSim.Region.Framework.Scenes.Tests | ||
45 | { | ||
46 | [TestFixture] | ||
47 | public class ScenePresenceCrossingTests : OpenSimTestCase | ||
48 | { | ||
49 | [TestFixtureSetUp] | ||
50 | public void FixtureInit() | ||
51 | { | ||
52 | // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. | ||
53 | Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; | ||
54 | } | ||
55 | |||
56 | [TestFixtureTearDown] | ||
57 | public void TearDown() | ||
58 | { | ||
59 | // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple | ||
60 | // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression | ||
61 | // tests really shouldn't). | ||
62 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | ||
63 | } | ||
64 | |||
65 | [Test] | ||
66 | public void TestCrossOnSameSimulator() | ||
67 | { | ||
68 | TestHelpers.InMethod(); | ||
69 | // TestHelpers.EnableLogging(); | ||
70 | |||
71 | UUID userId = TestHelpers.ParseTail(0x1); | ||
72 | |||
73 | // TestEventQueueGetModule eqmA = new TestEventQueueGetModule(); | ||
74 | EntityTransferModule etmA = new EntityTransferModule(); | ||
75 | EntityTransferModule etmB = new EntityTransferModule(); | ||
76 | LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); | ||
77 | |||
78 | IConfigSource config = new IniConfigSource(); | ||
79 | IConfig modulesConfig = config.AddConfig("Modules"); | ||
80 | modulesConfig.Set("EntityTransferModule", etmA.Name); | ||
81 | modulesConfig.Set("SimulationServices", lscm.Name); | ||
82 | // IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); | ||
83 | |||
84 | // In order to run a single threaded regression test we do not want the entity transfer module waiting | ||
85 | // for a callback from the destination scene before removing its avatar data. | ||
86 | // entityTransferConfig.Set("wait_for_callback", false); | ||
87 | |||
88 | SceneHelpers sh = new SceneHelpers(); | ||
89 | TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); | ||
90 | TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); | ||
91 | |||
92 | SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); | ||
93 | SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); | ||
94 | // SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, eqmA); | ||
95 | SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); | ||
96 | |||
97 | ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); | ||
98 | originalSp.AbsolutePosition = new Vector3(128, 32, 10); | ||
99 | |||
100 | // originalSp.Flying = true; | ||
101 | |||
102 | // Console.WriteLine("First pos {0}", originalSp.AbsolutePosition); | ||
103 | |||
104 | // eqmA.ClearEvents(); | ||
105 | |||
106 | AgentUpdateArgs moveArgs = new AgentUpdateArgs(); | ||
107 | //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); | ||
108 | moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); | ||
109 | moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; | ||
110 | |||
111 | originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); | ||
112 | |||
113 | sceneA.Update(1); | ||
114 | |||
115 | // Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition); | ||
116 | |||
117 | // FIXME: This is a sufficient number of updates to for the presence to reach the northern border. | ||
118 | // But really we want to do this in a more robust way. | ||
119 | for (int i = 0; i < 100; i++) | ||
120 | { | ||
121 | sceneA.Update(1); | ||
122 | // Console.WriteLine("Pos {0}", originalSp.AbsolutePosition); | ||
123 | } | ||
124 | |||
125 | // Need to sort processing of EnableSimulator message on adding scene presences before we can test eqm | ||
126 | // messages | ||
127 | // Dictionary<UUID, List<TestEventQueueGetModule.Event>> eqmEvents = eqmA.Events; | ||
128 | // | ||
129 | // Assert.That(eqmEvents.Count, Is.EqualTo(1)); | ||
130 | // Assert.That(eqmEvents.ContainsKey(originalSp.UUID), Is.True); | ||
131 | // | ||
132 | // List<TestEventQueueGetModule.Event> spEqmEvents = eqmEvents[originalSp.UUID]; | ||
133 | // | ||
134 | // Assert.That(spEqmEvents.Count, Is.EqualTo(1)); | ||
135 | // Assert.That(spEqmEvents[0].Name, Is.EqualTo("CrossRegion")); | ||
136 | |||
137 | // sceneA should now only have a child agent | ||
138 | ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID); | ||
139 | Assert.That(spAfterCrossSceneA.IsChildAgent, Is.True); | ||
140 | |||
141 | ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID); | ||
142 | |||
143 | // Agent remains a child until the client triggers complete movement | ||
144 | Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); | ||
145 | |||
146 | TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient); | ||
147 | |||
148 | int agentMovementCompleteReceived = 0; | ||
149 | sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++; | ||
150 | |||
151 | sceneBTc.CompleteMovement(); | ||
152 | |||
153 | Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); | ||
154 | Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); | ||
155 | } | ||
156 | } | ||
157 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs index a3d2436..6e74ce0 100644 --- a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs +++ b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs | |||
@@ -140,9 +140,12 @@ public class ServerStats : ISharedRegionModule | |||
140 | } | 140 | } |
141 | #endregion ISharedRegionModule | 141 | #endregion ISharedRegionModule |
142 | 142 | ||
143 | private void MakeStat(string pName, string pUnit, string pContainer, Action<Stat> act) | 143 | private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act) |
144 | { | 144 | { |
145 | Stat stat = new Stat(pName, pName, "", pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); | 145 | string desc = pDesc; |
146 | if (desc == null) | ||
147 | desc = pName; | ||
148 | Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); | ||
146 | StatsManager.RegisterStat(stat); | 149 | StatsManager.RegisterStat(stat); |
147 | RegisteredStats.Add(pName, stat); | 150 | RegisteredStats.Add(pName, stat); |
148 | } | 151 | } |
@@ -166,16 +169,16 @@ public class ServerStats : ISharedRegionModule | |||
166 | StatsManager.RegisterStat(tempStat); | 169 | StatsManager.RegisterStat(tempStat); |
167 | RegisteredStats.Add(tempName, tempStat); | 170 | RegisteredStats.Add(tempName, tempStat); |
168 | 171 | ||
169 | MakeStat("TotalProcessorTime", "sec", ContainerProcessor, | 172 | MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, |
170 | (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); | 173 | (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); |
171 | 174 | ||
172 | MakeStat("UserProcessorTime", "sec", ContainerProcessor, | 175 | MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, |
173 | (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); | 176 | (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); |
174 | 177 | ||
175 | MakeStat("PrivilegedProcessorTime", "sec", ContainerProcessor, | 178 | MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, |
176 | (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); | 179 | (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); |
177 | 180 | ||
178 | MakeStat("Threads", "threads", ContainerProcessor, | 181 | MakeStat("Threads", null, "threads", ContainerProcessor, |
179 | (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); | 182 | (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); |
180 | } | 183 | } |
181 | catch (Exception e) | 184 | catch (Exception e) |
@@ -196,8 +199,10 @@ public class ServerStats : ISharedRegionModule | |||
196 | string nicInterfaceType = nic.NetworkInterfaceType.ToString(); | 199 | string nicInterfaceType = nic.NetworkInterfaceType.ToString(); |
197 | if (!okInterfaceTypes.Contains(nicInterfaceType)) | 200 | if (!okInterfaceTypes.Contains(nicInterfaceType)) |
198 | { | 201 | { |
199 | m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'. To include, add to [Monitoring]NetworkInterfaceTypes='Ethernet,Loopback'", | 202 | m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.", |
200 | LogHeader, nic.Name, nicInterfaceType); | 203 | LogHeader, nic.Name, nicInterfaceType); |
204 | m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}", | ||
205 | LogHeader, NetworkInterfaceTypes); | ||
201 | continue; | 206 | continue; |
202 | } | 207 | } |
203 | 208 | ||
@@ -206,14 +211,15 @@ public class ServerStats : ISharedRegionModule | |||
206 | IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); | 211 | IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); |
207 | if (nicStats != null) | 212 | if (nicStats != null) |
208 | { | 213 | { |
209 | MakeStat("BytesRcvd/" + nic.Name, "KB", ContainerNetwork, | 214 | MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork, |
210 | (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); | 215 | (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); |
211 | MakeStat("BytesSent/" + nic.Name, "KB", ContainerNetwork, | 216 | MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork, |
212 | (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); | 217 | (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); |
213 | MakeStat("TotalBytes/" + nic.Name, "KB", ContainerNetwork, | 218 | MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork, |
214 | (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); | 219 | (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); |
215 | } | 220 | } |
216 | } | 221 | } |
222 | // TODO: add IPv6 (it may actually happen someday) | ||
217 | } | 223 | } |
218 | } | 224 | } |
219 | catch (Exception e) | 225 | catch (Exception e) |
@@ -221,13 +227,13 @@ public class ServerStats : ISharedRegionModule | |||
221 | m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); | 227 | m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); |
222 | } | 228 | } |
223 | 229 | ||
224 | MakeStat("ProcessMemory", "MB", ContainerMemory, | 230 | MakeStat("ProcessMemory", null, "MB", ContainerMemory, |
225 | (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); | 231 | (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); |
226 | MakeStat("ObjectMemory", "MB", ContainerMemory, | 232 | MakeStat("ObjectMemory", null, "MB", ContainerMemory, |
227 | (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); | 233 | (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); |
228 | MakeStat("LastMemoryChurn", "MB/sec", ContainerMemory, | 234 | MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, |
229 | (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); | 235 | (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); |
230 | MakeStat("AverageMemoryChurn", "MB/sec", ContainerMemory, | 236 | MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, |
231 | (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); | 237 | (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); |
232 | } | 238 | } |
233 | 239 | ||
@@ -263,6 +269,8 @@ public class ServerStats : ISharedRegionModule | |||
263 | } | 269 | } |
264 | } | 270 | } |
265 | 271 | ||
272 | // Lookup the nic that goes with this stat and set the value by using a fetch action. | ||
273 | // Not sure about closure with delegates inside delegates. | ||
266 | private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); | 274 | private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); |
267 | private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) | 275 | private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) |
268 | { | 276 | { |
@@ -275,7 +283,10 @@ public class ServerStats : ISharedRegionModule | |||
275 | { | 283 | { |
276 | IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); | 284 | IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); |
277 | if (intrStats != null) | 285 | if (intrStats != null) |
278 | stat.Value = Math.Round(getter(intrStats) / factor, 3); | 286 | { |
287 | double newVal = Math.Round(getter(intrStats) / factor, 3); | ||
288 | stat.Value = newVal; | ||
289 | } | ||
279 | break; | 290 | break; |
280 | } | 291 | } |
281 | } | 292 | } |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs index 40adba1..e498c6a 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs | |||
@@ -145,7 +145,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
145 | /// | 145 | /// |
146 | /// </summary> | 146 | /// </summary> |
147 | // ----------------------------------------------------------------- | 147 | // ----------------------------------------------------------------- |
148 | public JsonStoreNodeType PathType(string expr) | 148 | public JsonStoreNodeType GetNodeType(string expr) |
149 | { | 149 | { |
150 | Stack<string> path; | 150 | Stack<string> path; |
151 | if (! ParsePathExpression(expr,out path)) | 151 | if (! ParsePathExpression(expr,out path)) |
@@ -173,6 +173,43 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
173 | /// | 173 | /// |
174 | /// </summary> | 174 | /// </summary> |
175 | // ----------------------------------------------------------------- | 175 | // ----------------------------------------------------------------- |
176 | public JsonStoreValueType GetValueType(string expr) | ||
177 | { | ||
178 | Stack<string> path; | ||
179 | if (! ParsePathExpression(expr,out path)) | ||
180 | return JsonStoreValueType.Undefined; | ||
181 | |||
182 | OSD result = ProcessPathExpression(ValueStore,path); | ||
183 | |||
184 | if (result == null) | ||
185 | return JsonStoreValueType.Undefined; | ||
186 | |||
187 | if (result is OSDMap) | ||
188 | return JsonStoreValueType.Undefined; | ||
189 | |||
190 | if (result is OSDArray) | ||
191 | return JsonStoreValueType.Undefined; | ||
192 | |||
193 | if (result is OSDBoolean) | ||
194 | return JsonStoreValueType.Boolean; | ||
195 | |||
196 | if (result is OSDInteger) | ||
197 | return JsonStoreValueType.Integer; | ||
198 | |||
199 | if (result is OSDReal) | ||
200 | return JsonStoreValueType.Float; | ||
201 | |||
202 | if (result is OSDString) | ||
203 | return JsonStoreValueType.String; | ||
204 | |||
205 | return JsonStoreValueType.Undefined; | ||
206 | } | ||
207 | |||
208 | // ----------------------------------------------------------------- | ||
209 | /// <summary> | ||
210 | /// | ||
211 | /// </summary> | ||
212 | // ----------------------------------------------------------------- | ||
176 | public int ArrayLength(string expr) | 213 | public int ArrayLength(string expr) |
177 | { | 214 | { |
178 | Stack<string> path; | 215 | Stack<string> path; |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs index e78a2f4..5fbfcc5 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs | |||
@@ -270,7 +270,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
270 | /// | 270 | /// |
271 | /// </summary> | 271 | /// </summary> |
272 | // ----------------------------------------------------------------- | 272 | // ----------------------------------------------------------------- |
273 | public JsonStoreNodeType GetPathType(UUID storeID, string path) | 273 | public JsonStoreNodeType GetNodeType(UUID storeID, string path) |
274 | { | 274 | { |
275 | if (! m_enabled) return JsonStoreNodeType.Undefined; | 275 | if (! m_enabled) return JsonStoreNodeType.Undefined; |
276 | 276 | ||
@@ -287,7 +287,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
287 | try | 287 | try |
288 | { | 288 | { |
289 | lock (map) | 289 | lock (map) |
290 | return map.PathType(path); | 290 | return map.GetNodeType(path); |
291 | } | 291 | } |
292 | catch (Exception e) | 292 | catch (Exception e) |
293 | { | 293 | { |
@@ -302,6 +302,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
302 | /// | 302 | /// |
303 | /// </summary> | 303 | /// </summary> |
304 | // ----------------------------------------------------------------- | 304 | // ----------------------------------------------------------------- |
305 | public JsonStoreValueType GetValueType(UUID storeID, string path) | ||
306 | { | ||
307 | if (! m_enabled) return JsonStoreValueType.Undefined; | ||
308 | |||
309 | JsonStore map = null; | ||
310 | lock (m_JsonValueStore) | ||
311 | { | ||
312 | if (! m_JsonValueStore.TryGetValue(storeID,out map)) | ||
313 | { | ||
314 | m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); | ||
315 | return JsonStoreValueType.Undefined; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | try | ||
320 | { | ||
321 | lock (map) | ||
322 | return map.GetValueType(path); | ||
323 | } | ||
324 | catch (Exception e) | ||
325 | { | ||
326 | m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e); | ||
327 | } | ||
328 | |||
329 | return JsonStoreValueType.Undefined; | ||
330 | } | ||
331 | |||
332 | // ----------------------------------------------------------------- | ||
333 | /// <summary> | ||
334 | /// | ||
335 | /// </summary> | ||
336 | // ----------------------------------------------------------------- | ||
305 | public bool SetValue(UUID storeID, string path, string value, bool useJson) | 337 | public bool SetValue(UUID storeID, string path, string value, bool useJson) |
306 | { | 338 | { |
307 | if (! m_enabled) return false; | 339 | if (! m_enabled) return false; |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index e13eb56..4a754a9 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs | |||
@@ -192,16 +192,32 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
192 | #region ScriptConstantsInterface | 192 | #region ScriptConstantsInterface |
193 | 193 | ||
194 | [ScriptConstant] | 194 | [ScriptConstant] |
195 | public static readonly int JSON_TYPE_UNDEF = (int)JsonStoreNodeType.Undefined; | 195 | public static readonly int JSON_NODETYPE_UNDEF = (int)JsonStoreNodeType.Undefined; |
196 | 196 | ||
197 | [ScriptConstant] | 197 | [ScriptConstant] |
198 | public static readonly int JSON_TYPE_OBJECT = (int)JsonStoreNodeType.Object; | 198 | public static readonly int JSON_NODETYPE_OBJECT = (int)JsonStoreNodeType.Object; |
199 | 199 | ||
200 | [ScriptConstant] | 200 | [ScriptConstant] |
201 | public static readonly int JSON_TYPE_ARRAY = (int)JsonStoreNodeType.Array; | 201 | public static readonly int JSON_NODETYPE_ARRAY = (int)JsonStoreNodeType.Array; |
202 | 202 | ||
203 | [ScriptConstant] | 203 | [ScriptConstant] |
204 | public static readonly int JSON_TYPE_VALUE = (int)JsonStoreNodeType.Value; | 204 | public static readonly int JSON_NODETYPE_VALUE = (int)JsonStoreNodeType.Value; |
205 | |||
206 | [ScriptConstant] | ||
207 | public static readonly int JSON_VALUETYPE_UNDEF = (int)JsonStoreValueType.Undefined; | ||
208 | |||
209 | [ScriptConstant] | ||
210 | public static readonly int JSON_VALUETYPE_BOOLEAN = (int)JsonStoreValueType.Boolean; | ||
211 | |||
212 | [ScriptConstant] | ||
213 | public static readonly int JSON_VALUETYPE_INTEGER = (int)JsonStoreValueType.Integer; | ||
214 | |||
215 | [ScriptConstant] | ||
216 | public static readonly int JSON_VALUETYPE_FLOAT = (int)JsonStoreValueType.Float; | ||
217 | |||
218 | [ScriptConstant] | ||
219 | public static readonly int JSON_VALUETYPE_STRING = (int)JsonStoreValueType.String; | ||
220 | |||
205 | 221 | ||
206 | #endregion | 222 | #endregion |
207 | 223 | ||
@@ -310,9 +326,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
310 | /// </summary> | 326 | /// </summary> |
311 | // ----------------------------------------------------------------- | 327 | // ----------------------------------------------------------------- |
312 | [ScriptInvocation] | 328 | [ScriptInvocation] |
313 | public int JsonGetPathType(UUID hostID, UUID scriptID, UUID storeID, string path) | 329 | public int JsonGetNodeType(UUID hostID, UUID scriptID, UUID storeID, string path) |
330 | { | ||
331 | return (int)m_store.GetNodeType(storeID,path); | ||
332 | } | ||
333 | |||
334 | // ----------------------------------------------------------------- | ||
335 | /// <summary> | ||
336 | /// | ||
337 | /// </summary> | ||
338 | // ----------------------------------------------------------------- | ||
339 | [ScriptInvocation] | ||
340 | public int JsonGetValueType(UUID hostID, UUID scriptID, UUID storeID, string path) | ||
314 | { | 341 | { |
315 | return (int)m_store.GetPathType(storeID,path); | 342 | return (int)m_store.GetValueType(storeID,path); |
316 | } | 343 | } |
317 | 344 | ||
318 | // ----------------------------------------------------------------- | 345 | // ----------------------------------------------------------------- |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs index b64dbd4..bfa9937 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs | |||
@@ -158,8 +158,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
158 | 158 | ||
159 | Assert.That(dsrv, Is.EqualTo(1)); | 159 | Assert.That(dsrv, Is.EqualTo(1)); |
160 | 160 | ||
161 | int tprv = (int)InvokeOp("JsonGetPathType", storeId, "Hello"); | 161 | int tprv = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); |
162 | Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | 162 | Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); |
163 | } | 163 | } |
164 | 164 | ||
165 | [Test] | 165 | [Test] |
@@ -277,8 +277,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
277 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | 277 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); |
278 | Assert.That(returnValue, Is.EqualTo(1)); | 278 | Assert.That(returnValue, Is.EqualTo(1)); |
279 | 279 | ||
280 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello"); | 280 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); |
281 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | 281 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); |
282 | 282 | ||
283 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | 283 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); |
284 | Assert.That(returnValue2, Is.EqualTo("")); | 284 | Assert.That(returnValue2, Is.EqualTo("")); |
@@ -291,8 +291,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
291 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | 291 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); |
292 | Assert.That(returnValue, Is.EqualTo(1)); | 292 | Assert.That(returnValue, Is.EqualTo(1)); |
293 | 293 | ||
294 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello"); | 294 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); |
295 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | 295 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); |
296 | 296 | ||
297 | string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello"); | 297 | string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello"); |
298 | Assert.That(returnValue2, Is.EqualTo("")); | 298 | Assert.That(returnValue2, Is.EqualTo("")); |
@@ -306,11 +306,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
306 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); | 306 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); |
307 | Assert.That(returnValue, Is.EqualTo(1)); | 307 | Assert.That(returnValue, Is.EqualTo(1)); |
308 | 308 | ||
309 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[0]"); | 309 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[0]"); |
310 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE)); | 310 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); |
311 | 311 | ||
312 | result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[1]"); | 312 | result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[1]"); |
313 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | 313 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); |
314 | 314 | ||
315 | string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); | 315 | string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); |
316 | Assert.That(stringReturnValue, Is.EqualTo("value2")); | 316 | Assert.That(stringReturnValue, Is.EqualTo("value2")); |
@@ -433,7 +433,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
433 | } | 433 | } |
434 | 434 | ||
435 | [Test] | 435 | [Test] |
436 | public void TestJsonGetPathType() | 436 | public void TestJsonGetNodeType() |
437 | { | 437 | { |
438 | TestHelpers.InMethod(); | 438 | TestHelpers.InMethod(); |
439 | // TestHelpers.EnableLogging(); | 439 | // TestHelpers.EnableLogging(); |
@@ -441,41 +441,41 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
441 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); | 441 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); |
442 | 442 | ||
443 | { | 443 | { |
444 | int result = (int)InvokeOp("JsonGetPathType", storeId, "."); | 444 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "."); |
445 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT)); | 445 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT)); |
446 | } | 446 | } |
447 | 447 | ||
448 | { | 448 | { |
449 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello"); | 449 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); |
450 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT)); | 450 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT)); |
451 | } | 451 | } |
452 | 452 | ||
453 | { | 453 | { |
454 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World"); | 454 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World"); |
455 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_ARRAY)); | 455 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_ARRAY)); |
456 | } | 456 | } |
457 | 457 | ||
458 | { | 458 | { |
459 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[0]"); | 459 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[0]"); |
460 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE)); | 460 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); |
461 | } | 461 | } |
462 | 462 | ||
463 | { | 463 | { |
464 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[1]"); | 464 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[1]"); |
465 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE)); | 465 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); |
466 | } | 466 | } |
467 | 467 | ||
468 | // Test for non-existant path | 468 | // Test for non-existant path |
469 | { | 469 | { |
470 | int result = (int)InvokeOp("JsonGetPathType", storeId, "foo"); | 470 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "foo"); |
471 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | 471 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); |
472 | } | 472 | } |
473 | 473 | ||
474 | // Test for non-existant store | 474 | // Test for non-existant store |
475 | { | 475 | { |
476 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 476 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); |
477 | int result = (int)InvokeOp("JsonGetPathType", fakeStoreId, "."); | 477 | int result = (int)InvokeOp("JsonGetNodeType", fakeStoreId, "."); |
478 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | 478 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); |
479 | } | 479 | } |
480 | } | 480 | } |
481 | 481 | ||
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs index c4b9117..0816b7b 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs | |||
@@ -102,6 +102,8 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin | |||
102 | 102 | ||
103 | public override float Simulate(float timeStep) | 103 | public override float Simulate(float timeStep) |
104 | { | 104 | { |
105 | // Console.WriteLine("Simulating"); | ||
106 | |||
105 | float fps = 0; | 107 | float fps = 0; |
106 | for (int i = 0; i < _actors.Count; ++i) | 108 | for (int i = 0; i < _actors.Count; ++i) |
107 | { | 109 | { |
@@ -109,8 +111,11 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin | |||
109 | Vector3 actorPosition = actor.Position; | 111 | Vector3 actorPosition = actor.Position; |
110 | Vector3 actorVelocity = actor.Velocity; | 112 | Vector3 actorVelocity = actor.Velocity; |
111 | 113 | ||
112 | actorPosition.X += actor.Velocity.X*timeStep; | 114 | // Console.WriteLine( |
113 | actorPosition.Y += actor.Velocity.Y*timeStep; | 115 | // "Processing actor {0}, starting pos {1}, starting vel {2}", i, actorPosition, actorVelocity); |
116 | |||
117 | actorPosition.X += actor.Velocity.X * timeStep; | ||
118 | actorPosition.Y += actor.Velocity.Y * timeStep; | ||
114 | 119 | ||
115 | if (actor.Position.Y < 0) | 120 | if (actor.Position.Y < 0) |
116 | { | 121 | { |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f442ca2..e208d3a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -205,7 +205,7 @@ public sealed class BSCharacter : BSPhysObject | |||
205 | // errors can creap in and the avatar will slowly float off in some direction. | 205 | // errors can creap in and the avatar will slowly float off in some direction. |
206 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error | 206 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error |
207 | // from real pushing. | 207 | // from real pushing. |
208 | // The code below keeps setting the velocity to zero hoping the world will keep pushing. | 208 | // The code below uses whether the collider is static or moving to decide whether to zero motion. |
209 | 209 | ||
210 | _velocityMotor.Step(timeStep); | 210 | _velocityMotor.Step(timeStep); |
211 | 211 | ||
@@ -244,6 +244,7 @@ public sealed class BSCharacter : BSPhysObject | |||
244 | } | 244 | } |
245 | else | 245 | else |
246 | { | 246 | { |
247 | // Supposed to be moving. | ||
247 | OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; | 248 | OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; |
248 | 249 | ||
249 | if (Friction != BSParam.AvatarFriction) | 250 | if (Friction != BSParam.AvatarFriction) |
@@ -276,8 +277,8 @@ public sealed class BSCharacter : BSPhysObject | |||
276 | }); | 277 | }); |
277 | } | 278 | } |
278 | 279 | ||
279 | // Decide of the character is colliding with a low object and compute a force to pop the | 280 | // Decide if the character is colliding with a low object and compute a force to pop the |
280 | // avatar up so it has a chance of walking up and over the low object. | 281 | // avatar up so it can walk up and over the low objects. |
281 | private OMV.Vector3 WalkUpStairs() | 282 | private OMV.Vector3 WalkUpStairs() |
282 | { | 283 | { |
283 | OMV.Vector3 ret = OMV.Vector3.Zero; | 284 | OMV.Vector3 ret = OMV.Vector3.Zero; |
@@ -476,17 +477,19 @@ public sealed class BSCharacter : BSPhysObject | |||
476 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) | 477 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) |
477 | { | 478 | { |
478 | // The character is out of the known/simulated area. | 479 | // The character is out of the known/simulated area. |
479 | // Upper levels of code will handle the transition to other areas so, for | 480 | // Force the avatar position to be within known. ScenePresence will use the position |
480 | // the time, we just ignore the position. | 481 | // plus the velocity to decide if the avatar is moving out of the region. |
481 | return ret; | 482 | RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); |
483 | DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); | ||
484 | return true; | ||
482 | } | 485 | } |
483 | 486 | ||
484 | // If below the ground, move the avatar up | 487 | // If below the ground, move the avatar up |
485 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 488 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
486 | if (Position.Z < terrainHeight) | 489 | if (Position.Z < terrainHeight) |
487 | { | 490 | { |
488 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 491 | DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
489 | _position.Z = terrainHeight + 2.0f; | 492 | _position.Z = terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters; |
490 | ret = true; | 493 | ret = true; |
491 | } | 494 | } |
492 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 495 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
@@ -806,14 +809,7 @@ public sealed class BSCharacter : BSPhysObject | |||
806 | private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | 809 | private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
807 | if (force.IsFinite()) | 810 | if (force.IsFinite()) |
808 | { | 811 | { |
809 | float magnitude = force.Length(); | 812 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
810 | if (magnitude > BSParam.MaxAddForceMagnitude) | ||
811 | { | ||
812 | // Force has a limit | ||
813 | force = force / magnitude * BSParam.MaxAddForceMagnitude; | ||
814 | } | ||
815 | |||
816 | OMV.Vector3 addForce = force; | ||
817 | // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); | 813 | // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); |
818 | 814 | ||
819 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() | 815 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() |
@@ -902,6 +898,7 @@ public sealed class BSCharacter : BSPhysObject | |||
902 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | 898 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. |
903 | if (PositionSanityCheck(true)) | 899 | if (PositionSanityCheck(true)) |
904 | { | 900 | { |
901 | DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); | ||
905 | entprop.Position = _position; | 902 | entprop.Position = _position; |
906 | } | 903 | } |
907 | 904 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 235cefc..38596fa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -143,7 +143,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
143 | { | 143 | { |
144 | enableAngularVerticalAttraction = true; | 144 | enableAngularVerticalAttraction = true; |
145 | enableAngularDeflection = false; | 145 | enableAngularDeflection = false; |
146 | enableAngularBanking = false; | 146 | enableAngularBanking = true; |
147 | if (BSParam.VehicleDebuggingEnabled) | 147 | if (BSParam.VehicleDebuggingEnabled) |
148 | { | 148 | { |
149 | enableAngularVerticalAttraction = true; | 149 | enableAngularVerticalAttraction = true; |
@@ -1280,11 +1280,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1280 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | 1280 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement |
1281 | // TODO: This is here because this is where ODE put it but documentation says it | 1281 | // TODO: This is here because this is where ODE put it but documentation says it |
1282 | // is a linear effect. Where should this check go? | 1282 | // is a linear effect. Where should this check go? |
1283 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | 1283 | //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) |
1284 | { | 1284 | // { |
1285 | angularMotorContributionV.X = 0f; | 1285 | // angularMotorContributionV.X = 0f; |
1286 | angularMotorContributionV.Y = 0f; | 1286 | // angularMotorContributionV.Y = 0f; |
1287 | } | 1287 | // } |
1288 | 1288 | ||
1289 | VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; | 1289 | VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; |
1290 | VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); | 1290 | VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); |
@@ -1335,7 +1335,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1335 | Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG | 1335 | Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG |
1336 | vertContributionV /= m_verticalAttractionTimescale; | 1336 | vertContributionV /= m_verticalAttractionTimescale; |
1337 | 1337 | ||
1338 | VehicleRotationalVelocity += vertContributionV * VehicleOrientation; | 1338 | VehicleRotationalVelocity += vertContributionV; |
1339 | 1339 | ||
1340 | VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", | 1340 | VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", |
1341 | Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, | 1341 | Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, |
@@ -1437,24 +1437,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1437 | // As the vehicle rolls to the right or left, the Y value will increase from | 1437 | // As the vehicle rolls to the right or left, the Y value will increase from |
1438 | // zero (straight up) to 1 or -1 (full tilt right or left) | 1438 | // zero (straight up) to 1 or -1 (full tilt right or left) |
1439 | Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; | 1439 | Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; |
1440 | |||
1441 | // Figure out the yaw value for this much roll. | ||
1442 | // Squared because that seems to give a good value | ||
1443 | float yawAngle = (float)Math.Asin(rollComponents.Y * rollComponents.Y) * m_bankingEfficiency; | ||
1444 | 1440 | ||
1441 | // Figure out the yaw value for this much roll. | ||
1442 | float yawAngle = m_angularMotorDirection.X * m_bankingEfficiency; | ||
1445 | // actual error = static turn error + dynamic turn error | 1443 | // actual error = static turn error + dynamic turn error |
1446 | float mixedYawAngle = yawAngle * (1f - m_bankingMix) + yawAngle * m_bankingMix * VehicleForwardSpeed; | 1444 | float mixedYawAngle =(yawAngle * (1f - m_bankingMix)) + ((yawAngle * m_bankingMix) * VehicleForwardSpeed); |
1447 | 1445 | ||
1448 | // TODO: the banking effect should not go to infinity but what to limit it to? | 1446 | // TODO: the banking effect should not go to infinity but what to limit it to? |
1449 | mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f); | 1447 | // And what should happen when this is being added to a user defined yaw that is already PI*4? |
1448 | mixedYawAngle = ClampInRange(-12, mixedYawAngle, 12); | ||
1450 | 1449 | ||
1451 | // Build the force vector to change rotation from what it is to what it should be | 1450 | // Build the force vector to change rotation from what it is to what it should be |
1452 | bankingContributionV.Z = -mixedYawAngle; | 1451 | bankingContributionV.Z = -mixedYawAngle; |
1453 | 1452 | ||
1454 | // Don't do it all at once. | 1453 | // Don't do it all at once. Fudge because 1 second is too fast with most user defined roll as PI*4. |
1455 | bankingContributionV /= m_bankingTimescale; | 1454 | bankingContributionV /= m_bankingTimescale * BSParam.VehicleAngularBankingTimescaleFudge; |
1456 | 1455 | ||
1457 | VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; | 1456 | //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; |
1457 | VehicleRotationalVelocity += bankingContributionV; | ||
1458 | |||
1458 | 1459 | ||
1459 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", | 1460 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", |
1460 | Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); | 1461 | Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index fa58109..77bdacb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | |||
@@ -107,6 +107,7 @@ public static class BSParam | |||
107 | public static float AvatarCapsuleDepth { get; private set; } | 107 | public static float AvatarCapsuleDepth { get; private set; } |
108 | public static float AvatarCapsuleHeight { get; private set; } | 108 | public static float AvatarCapsuleHeight { get; private set; } |
109 | public static float AvatarContactProcessingThreshold { get; private set; } | 109 | public static float AvatarContactProcessingThreshold { get; private set; } |
110 | public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } | ||
110 | public static float AvatarStepHeight { get; private set; } | 111 | public static float AvatarStepHeight { get; private set; } |
111 | public static float AvatarStepApproachFactor { get; private set; } | 112 | public static float AvatarStepApproachFactor { get; private set; } |
112 | public static float AvatarStepForceFactor { get; private set; } | 113 | public static float AvatarStepForceFactor { get; private set; } |
@@ -122,6 +123,7 @@ public static class BSParam | |||
122 | public static Vector3 VehicleLinearFactor { get; private set; } | 123 | public static Vector3 VehicleLinearFactor { get; private set; } |
123 | public static Vector3 VehicleAngularFactor { get; private set; } | 124 | public static Vector3 VehicleAngularFactor { get; private set; } |
124 | public static float VehicleGroundGravityFudge { get; private set; } | 125 | public static float VehicleGroundGravityFudge { get; private set; } |
126 | public static float VehicleAngularBankingTimescaleFudge { get; private set; } | ||
125 | public static bool VehicleDebuggingEnabled { get; private set; } | 127 | public static bool VehicleDebuggingEnabled { get; private set; } |
126 | 128 | ||
127 | // Linkset implementation parameters | 129 | // Linkset implementation parameters |
@@ -497,6 +499,10 @@ public static class BSParam | |||
497 | 0.1f, | 499 | 0.1f, |
498 | (s) => { return AvatarContactProcessingThreshold; }, | 500 | (s) => { return AvatarContactProcessingThreshold; }, |
499 | (s,v) => { AvatarContactProcessingThreshold = v; } ), | 501 | (s,v) => { AvatarContactProcessingThreshold = v; } ), |
502 | new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", | ||
503 | 1.0f, | ||
504 | (s) => { return AvatarBelowGroundUpCorrectionMeters; }, | ||
505 | (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ), | ||
500 | new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", | 506 | new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", |
501 | 0.3f, | 507 | 0.3f, |
502 | (s) => { return AvatarStepHeight; }, | 508 | (s) => { return AvatarStepHeight; }, |
@@ -538,10 +544,14 @@ public static class BSParam | |||
538 | 0.0f, | 544 | 0.0f, |
539 | (s) => { return VehicleRestitution; }, | 545 | (s) => { return VehicleRestitution; }, |
540 | (s,v) => { VehicleRestitution = v; } ), | 546 | (s,v) => { VehicleRestitution = v; } ), |
541 | new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", | 547 | new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", |
542 | 0.2f, | 548 | 0.2f, |
543 | (s) => { return VehicleGroundGravityFudge; }, | 549 | (s) => { return VehicleGroundGravityFudge; }, |
544 | (s,v) => { VehicleGroundGravityFudge = v; } ), | 550 | (s,v) => { VehicleGroundGravityFudge = v; } ), |
551 | new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", | ||
552 | 60.0f, | ||
553 | (s) => { return VehicleAngularBankingTimescaleFudge; }, | ||
554 | (s,v) => { VehicleAngularBankingTimescaleFudge = v; } ), | ||
545 | new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", | 555 | new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", |
546 | false, | 556 | false, |
547 | (s) => { return VehicleDebuggingEnabled; }, | 557 | (s) => { return VehicleDebuggingEnabled; }, |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 2e9db39..e8040d8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | |||
@@ -337,6 +337,54 @@ public sealed class BSTerrainManager : IDisposable | |||
337 | return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); | 337 | return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); |
338 | } | 338 | } |
339 | 339 | ||
340 | // Return a new position that is over known terrain if the position is outside our terrain. | ||
341 | public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) | ||
342 | { | ||
343 | Vector3 ret = pPos; | ||
344 | |||
345 | // Can't do this function if we don't know about any terrain. | ||
346 | if (m_terrains.Count == 0) | ||
347 | return ret; | ||
348 | |||
349 | int loopPrevention = 5; | ||
350 | Vector3 terrainBaseXYZ; | ||
351 | BSTerrainPhys physTerrain; | ||
352 | while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ)) | ||
353 | { | ||
354 | // The passed position is not within a known terrain area. | ||
355 | |||
356 | // First, base addresses are never negative so correct for that possible problem. | ||
357 | if (ret.X < 0f || ret.Y < 0f) | ||
358 | { | ||
359 | if (ret.X < 0f) | ||
360 | ret.X = 0f; | ||
361 | if (ret.Y < 0f) | ||
362 | ret.Y = 0f; | ||
363 | DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}", | ||
364 | BSScene.DetailLogZero, pPos, ret); | ||
365 | } | ||
366 | else | ||
367 | { | ||
368 | // Must be off the top of a region. Find an adjacent region to move into. | ||
369 | Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); | ||
370 | |||
371 | ret.X = Math.Min(ret.X, adjacentTerrainBase.X + DefaultRegionSize.X); | ||
372 | ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + DefaultRegionSize.Y); | ||
373 | DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", | ||
374 | BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); | ||
375 | } | ||
376 | if (loopPrevention-- < 0f) | ||
377 | { | ||
378 | // The 'while' is a little dangerous so this prevents looping forever if the | ||
379 | // mapping of the terrains ever gets messed up (like nothing at <0,0>) or | ||
380 | // the list of terrains is in transition. | ||
381 | DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,suppressingFindAdjacentRegionLoop", BSScene.DetailLogZero); | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | return ret; | ||
386 | } | ||
387 | |||
340 | // Given an X and Y, find the height of the terrain. | 388 | // Given an X and Y, find the height of the terrain. |
341 | // Since we could be handling multiple terrains for a mega-region, | 389 | // Since we could be handling multiple terrains for a mega-region, |
342 | // the base of the region is calcuated assuming all regions are | 390 | // the base of the region is calcuated assuming all regions are |
@@ -400,18 +448,60 @@ public sealed class BSTerrainManager : IDisposable | |||
400 | // the descriptor class and the 'base' fo the addresses therein. | 448 | // the descriptor class and the 'base' fo the addresses therein. |
401 | private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) | 449 | private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) |
402 | { | 450 | { |
403 | int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; | 451 | bool ret = false; |
404 | int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; | 452 | |
405 | Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); | 453 | Vector3 terrainBaseXYZ = Vector3.Zero; |
454 | if (pos.X < 0f || pos.Y < 0f) | ||
455 | { | ||
456 | // We don't handle negative addresses so just make up a base that will not be found. | ||
457 | terrainBaseXYZ = new Vector3(-DefaultRegionSize.X, -DefaultRegionSize.Y, 0f); | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; | ||
462 | int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; | ||
463 | terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); | ||
464 | } | ||
406 | 465 | ||
407 | BSTerrainPhys physTerrain = null; | 466 | BSTerrainPhys physTerrain = null; |
408 | lock (m_terrains) | 467 | lock (m_terrains) |
409 | { | 468 | { |
410 | m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); | 469 | ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); |
411 | } | 470 | } |
412 | outTerrainBase = terrainBaseXYZ; | 471 | outTerrainBase = terrainBaseXYZ; |
413 | outPhysTerrain = physTerrain; | 472 | outPhysTerrain = physTerrain; |
414 | return (physTerrain != null); | 473 | return ret; |
474 | } | ||
475 | |||
476 | // Given a terrain base, return a terrain base for a terrain that is closer to <0,0> than | ||
477 | // this one. Usually used to return an out of bounds object to a known place. | ||
478 | private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase) | ||
479 | { | ||
480 | Vector3 ret = pTerrainBase; | ||
481 | ret.Z = 0f; | ||
482 | lock (m_terrains) | ||
483 | { | ||
484 | // Once down to the <0,0> region, we have to be done. | ||
485 | while (ret.X > 0f && ret.Y > 0f) | ||
486 | { | ||
487 | if (ret.X > 0f) | ||
488 | { | ||
489 | ret.X = Math.Max(0f, ret.X - DefaultRegionSize.X); | ||
490 | DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingX,terrainBase={1}", BSScene.DetailLogZero, ret); | ||
491 | if (m_terrains.ContainsKey(ret)) | ||
492 | break; | ||
493 | } | ||
494 | if (ret.Y > 0f) | ||
495 | { | ||
496 | ret.Y = Math.Max(0f, ret.Y - DefaultRegionSize.Y); | ||
497 | DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingY,terrainBase={1}", BSScene.DetailLogZero, ret); | ||
498 | if (m_terrains.ContainsKey(ret)) | ||
499 | break; | ||
500 | } | ||
501 | } | ||
502 | } | ||
503 | |||
504 | return ret; | ||
415 | } | 505 | } |
416 | 506 | ||
417 | // Although no one seems to check this, I do support combining. | 507 | // Although no one seems to check this, I do support combining. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index d7e800d..57a5ff2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs | |||
@@ -215,7 +215,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
215 | 215 | ||
216 | float magX = (float)sizeX / extentX; | 216 | float magX = (float)sizeX / extentX; |
217 | float magY = (float)sizeY / extentY; | 217 | float magY = (float)sizeY / extentY; |
218 | physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", | 218 | if (physicsScene != null) |
219 | physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", | ||
219 | BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); | 220 | BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); |
220 | float minHeight = float.MaxValue; | 221 | float minHeight = float.MaxValue; |
221 | // Note that sizeX+1 vertices are created since there is land between this and the next region. | 222 | // Note that sizeX+1 vertices are created since there is land between this and the next region. |
@@ -257,7 +258,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
257 | } | 258 | } |
258 | catch (Exception e) | 259 | catch (Exception e) |
259 | { | 260 | { |
260 | physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", | 261 | if (physicsScene != null) |
262 | physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", | ||
261 | LogHeader, physicsScene.RegionName, extentBase, e); | 263 | LogHeader, physicsScene.RegionName, extentBase, e); |
262 | } | 264 | } |
263 | 265 | ||
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs index a133e51..b4abc1d 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs | |||
@@ -68,6 +68,11 @@ public class RegionCombinerLargeLandChannel : ILandChannel | |||
68 | RootRegionLandChannel.Clear(setupDefaultParcel); | 68 | RootRegionLandChannel.Clear(setupDefaultParcel); |
69 | } | 69 | } |
70 | 70 | ||
71 | public ILandObject GetLandObject(Vector3 position) | ||
72 | { | ||
73 | return GetLandObject(position.X, position.Y); | ||
74 | } | ||
75 | |||
71 | public ILandObject GetLandObject(int x, int y) | 76 | public ILandObject GetLandObject(int x, int y) |
72 | { | 77 | { |
73 | //m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y); | 78 | //m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cf6f13e..e1f0071 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -283,6 +283,80 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | /// <summary> | ||
287 | /// Get a given link entity from a linkset (linked objects and any sitting avatars). | ||
288 | /// </summary> | ||
289 | /// <remarks> | ||
290 | /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then | ||
291 | /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset. | ||
292 | /// The ScenePresences receive linknums in the order in which they sat. | ||
293 | /// </remarks> | ||
294 | /// <returns> | ||
295 | /// The link entity. null if not found. | ||
296 | /// </returns> | ||
297 | /// <param name='linknum'> | ||
298 | /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). | ||
299 | /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. | ||
300 | /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any | ||
301 | /// positive integer is given in this case then null is returned. | ||
302 | /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number | ||
303 | /// of entities, then the entity which corresponds to that linknum is returned. | ||
304 | /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then | ||
305 | /// null is returned. | ||
306 | /// </param> | ||
307 | public ISceneEntity GetLinkEntity(int linknum) | ||
308 | { | ||
309 | if (linknum < 0) | ||
310 | { | ||
311 | if (linknum == ScriptBaseClass.LINK_THIS) | ||
312 | return m_host; | ||
313 | else | ||
314 | return null; | ||
315 | } | ||
316 | |||
317 | int actualPrimCount = m_host.ParentGroup.PrimCount; | ||
318 | List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); | ||
319 | int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; | ||
320 | |||
321 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | ||
322 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | ||
323 | if (linknum == 0) | ||
324 | { | ||
325 | if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) | ||
326 | return m_host; | ||
327 | |||
328 | return null; | ||
329 | } | ||
330 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | ||
331 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | ||
332 | else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) | ||
333 | { | ||
334 | if (sittingAvatarIds.Count > 0) | ||
335 | return m_host.ParentGroup.RootPart; | ||
336 | else | ||
337 | return null; | ||
338 | } | ||
339 | else if (linknum <= adjustedPrimCount) | ||
340 | { | ||
341 | if (linknum <= actualPrimCount) | ||
342 | { | ||
343 | return m_host.ParentGroup.GetLinkNumPart(linknum); | ||
344 | } | ||
345 | else | ||
346 | { | ||
347 | ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]); | ||
348 | if (sp != null) | ||
349 | return sp; | ||
350 | else | ||
351 | return null; | ||
352 | } | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | return null; | ||
357 | } | ||
358 | } | ||
359 | |||
286 | public List<SceneObjectPart> GetLinkParts(int linkType) | 360 | public List<SceneObjectPart> GetLinkParts(int linkType) |
287 | { | 361 | { |
288 | return GetLinkParts(m_host, linkType); | 362 | return GetLinkParts(m_host, linkType); |
@@ -2174,23 +2248,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2174 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 2248 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
2175 | q = avatar.CameraRotation; // Mouselook | 2249 | q = avatar.CameraRotation; // Mouselook |
2176 | else | 2250 | else |
2177 | q = avatar.Rotation; // Currently infrequently updated so may be inaccurate | 2251 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate |
2178 | } | 2252 | } |
2179 | else | 2253 | else |
2180 | q = part.ParentGroup.GroupRotation; // Likely never get here but just in case | 2254 | q = part.ParentGroup.GroupRotation; // Likely never get here but just in case |
2181 | } | 2255 | } |
2182 | else | 2256 | else |
2183 | q = part.ParentGroup.GroupRotation; // just the group rotation | 2257 | q = part.ParentGroup.GroupRotation; // just the group rotation |
2184 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 2258 | |
2259 | return new LSL_Rotation(q); | ||
2185 | } | 2260 | } |
2186 | q = part.GetWorldRotation(); | 2261 | |
2187 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 2262 | return new LSL_Rotation(part.GetWorldRotation()); |
2188 | } | 2263 | } |
2189 | 2264 | ||
2190 | public LSL_Rotation llGetLocalRot() | 2265 | public LSL_Rotation llGetLocalRot() |
2191 | { | 2266 | { |
2192 | m_host.AddScriptLPS(1); | 2267 | m_host.AddScriptLPS(1); |
2193 | return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); | 2268 | |
2269 | return new LSL_Rotation(m_host.RotationOffset); | ||
2194 | } | 2270 | } |
2195 | 2271 | ||
2196 | public void llSetForce(LSL_Vector force, int local) | 2272 | public void llSetForce(LSL_Vector force, int local) |
@@ -2285,8 +2361,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2285 | public LSL_Vector llGetTorque() | 2361 | public LSL_Vector llGetTorque() |
2286 | { | 2362 | { |
2287 | m_host.AddScriptLPS(1); | 2363 | m_host.AddScriptLPS(1); |
2288 | Vector3 torque = m_host.ParentGroup.GetTorque(); | 2364 | |
2289 | return new LSL_Vector(torque.X,torque.Y,torque.Z); | 2365 | return new LSL_Vector(m_host.ParentGroup.GetTorque()); |
2290 | } | 2366 | } |
2291 | 2367 | ||
2292 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) | 2368 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) |
@@ -2312,19 +2388,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2312 | vel = m_host.Velocity; | 2388 | vel = m_host.Velocity; |
2313 | } | 2389 | } |
2314 | 2390 | ||
2315 | return new LSL_Vector(vel.X, vel.Y, vel.Z); | 2391 | return new LSL_Vector(vel); |
2316 | } | 2392 | } |
2317 | 2393 | ||
2318 | public LSL_Vector llGetAccel() | 2394 | public LSL_Vector llGetAccel() |
2319 | { | 2395 | { |
2320 | m_host.AddScriptLPS(1); | 2396 | m_host.AddScriptLPS(1); |
2321 | return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); | 2397 | |
2398 | return new LSL_Vector(m_host.Acceleration); | ||
2322 | } | 2399 | } |
2323 | 2400 | ||
2324 | public LSL_Vector llGetOmega() | 2401 | public LSL_Vector llGetOmega() |
2325 | { | 2402 | { |
2326 | m_host.AddScriptLPS(1); | 2403 | m_host.AddScriptLPS(1); |
2327 | return new LSL_Vector(m_host.AngularVelocity.X, m_host.AngularVelocity.Y, m_host.AngularVelocity.Z); | 2404 | |
2405 | return new LSL_Vector(m_host.AngularVelocity); | ||
2328 | } | 2406 | } |
2329 | 2407 | ||
2330 | public LSL_Float llGetTimeOfDay() | 2408 | public LSL_Float llGetTimeOfDay() |
@@ -3101,13 +3179,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3101 | msg.ParentEstateID = 0; //ParentEstateID; | 3179 | msg.ParentEstateID = 0; //ParentEstateID; |
3102 | msg.Position = new Vector3(m_host.AbsolutePosition); | 3180 | msg.Position = new Vector3(m_host.AbsolutePosition); |
3103 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; | 3181 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; |
3182 | |||
3183 | Vector3 pos = m_host.AbsolutePosition; | ||
3104 | msg.binaryBucket | 3184 | msg.binaryBucket |
3105 | = Util.StringToBytes256( | 3185 | = Util.StringToBytes256( |
3106 | "{0}/{1}/{2}/{3}", | 3186 | "{0}/{1}/{2}/{3}", |
3107 | World.RegionInfo.RegionName, | 3187 | World.RegionInfo.RegionName, |
3108 | (int)Math.Floor(m_host.AbsolutePosition.X), | 3188 | (int)Math.Floor(pos.X), |
3109 | (int)Math.Floor(m_host.AbsolutePosition.Y), | 3189 | (int)Math.Floor(pos.Y), |
3110 | (int)Math.Floor(m_host.AbsolutePosition.Z)); | 3190 | (int)Math.Floor(pos.Z)); |
3111 | 3191 | ||
3112 | if (m_TransferModule != null) | 3192 | if (m_TransferModule != null) |
3113 | { | 3193 | { |
@@ -3691,47 +3771,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3691 | { | 3771 | { |
3692 | m_host.AddScriptLPS(1); | 3772 | m_host.AddScriptLPS(1); |
3693 | 3773 | ||
3694 | if (linknum < 0) | 3774 | ISceneEntity entity = GetLinkEntity(linknum); |
3695 | { | ||
3696 | if (linknum == ScriptBaseClass.LINK_THIS) | ||
3697 | return m_host.UUID.ToString(); | ||
3698 | else | ||
3699 | return ScriptBaseClass.NULL_KEY; | ||
3700 | } | ||
3701 | |||
3702 | int actualPrimCount = m_host.ParentGroup.PrimCount; | ||
3703 | List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); | ||
3704 | int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; | ||
3705 | |||
3706 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | ||
3707 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | ||
3708 | if (linknum == 0) | ||
3709 | { | ||
3710 | if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) | ||
3711 | return m_host.UUID.ToString(); | ||
3712 | 3775 | ||
3713 | return ScriptBaseClass.NULL_KEY; | 3776 | if (entity != null) |
3714 | } | 3777 | return entity.UUID.ToString(); |
3715 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | ||
3716 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | ||
3717 | else if (linknum == 1 && actualPrimCount == 1) | ||
3718 | { | ||
3719 | if (sittingAvatarIds.Count > 0) | ||
3720 | return m_host.ParentGroup.RootPart.UUID.ToString(); | ||
3721 | else | ||
3722 | return ScriptBaseClass.NULL_KEY; | ||
3723 | } | ||
3724 | else if (linknum <= adjustedPrimCount) | ||
3725 | { | ||
3726 | if (linknum <= actualPrimCount) | ||
3727 | return m_host.ParentGroup.GetLinkNumPart(linknum).UUID.ToString(); | ||
3728 | else | ||
3729 | return sittingAvatarIds[linknum - actualPrimCount - 1].ToString(); | ||
3730 | } | ||
3731 | else | 3778 | else |
3732 | { | ||
3733 | return ScriptBaseClass.NULL_KEY; | 3779 | return ScriptBaseClass.NULL_KEY; |
3734 | } | ||
3735 | } | 3780 | } |
3736 | 3781 | ||
3737 | /// <summary> | 3782 | /// <summary> |
@@ -3777,55 +3822,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3777 | { | 3822 | { |
3778 | m_host.AddScriptLPS(1); | 3823 | m_host.AddScriptLPS(1); |
3779 | 3824 | ||
3780 | if (linknum < 0) | 3825 | ISceneEntity entity = GetLinkEntity(linknum); |
3781 | { | ||
3782 | if (linknum == ScriptBaseClass.LINK_THIS) | ||
3783 | return m_host.Name; | ||
3784 | else | ||
3785 | return ScriptBaseClass.NULL_KEY; | ||
3786 | } | ||
3787 | 3826 | ||
3788 | int actualPrimCount = m_host.ParentGroup.PrimCount; | 3827 | if (entity != null) |
3789 | List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); | 3828 | return entity.Name; |
3790 | int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; | ||
3791 | |||
3792 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | ||
3793 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | ||
3794 | if (linknum == 0) | ||
3795 | { | ||
3796 | if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) | ||
3797 | return m_host.Name; | ||
3798 | |||
3799 | return ScriptBaseClass.NULL_KEY; | ||
3800 | } | ||
3801 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | ||
3802 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | ||
3803 | else if (linknum == 1 && actualPrimCount == 1) | ||
3804 | { | ||
3805 | if (sittingAvatarIds.Count > 0) | ||
3806 | return m_host.ParentGroup.RootPart.Name; | ||
3807 | else | ||
3808 | return ScriptBaseClass.NULL_KEY; | ||
3809 | } | ||
3810 | else if (linknum <= adjustedPrimCount) | ||
3811 | { | ||
3812 | if (linknum <= actualPrimCount) | ||
3813 | { | ||
3814 | return m_host.ParentGroup.GetLinkNumPart(linknum).Name; | ||
3815 | } | ||
3816 | else | ||
3817 | { | ||
3818 | ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]); | ||
3819 | if (sp != null) | ||
3820 | return sp.Name; | ||
3821 | else | ||
3822 | return ScriptBaseClass.NULL_KEY; | ||
3823 | } | ||
3824 | } | ||
3825 | else | 3829 | else |
3826 | { | ||
3827 | return ScriptBaseClass.NULL_KEY; | 3830 | return ScriptBaseClass.NULL_KEY; |
3828 | } | ||
3829 | } | 3831 | } |
3830 | 3832 | ||
3831 | public LSL_Integer llGetInventoryNumber(int type) | 3833 | public LSL_Integer llGetInventoryNumber(int type) |
@@ -4170,13 +4172,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4170 | if (presence != null) | 4172 | if (presence != null) |
4171 | { | 4173 | { |
4172 | // agent must be over the owners land | 4174 | // agent must be over the owners land |
4173 | if (m_host.OwnerID == World.LandChannel.GetLandObject( | 4175 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4174 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
4175 | { | 4176 | { |
4176 | World.TeleportClientHome(agentId, presence.ControllingClient); | 4177 | World.TeleportClientHome(agentId, presence.ControllingClient); |
4177 | } | 4178 | } |
4178 | } | 4179 | } |
4179 | } | 4180 | } |
4181 | |||
4180 | ScriptSleep(5000); | 4182 | ScriptSleep(5000); |
4181 | } | 4183 | } |
4182 | 4184 | ||
@@ -4197,8 +4199,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4197 | destination = World.RegionInfo.RegionName; | 4199 | destination = World.RegionInfo.RegionName; |
4198 | 4200 | ||
4199 | // agent must be over the owners land | 4201 | // agent must be over the owners land |
4200 | if (m_host.OwnerID == World.LandChannel.GetLandObject( | 4202 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4201 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
4202 | { | 4203 | { |
4203 | DoLLTeleport(presence, destination, targetPos, targetLookAt); | 4204 | DoLLTeleport(presence, destination, targetPos, targetLookAt); |
4204 | } | 4205 | } |
@@ -4229,8 +4230,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4229 | if (presence.GodLevel >= 200) return; | 4230 | if (presence.GodLevel >= 200) return; |
4230 | 4231 | ||
4231 | // agent must be over the owners land | 4232 | // agent must be over the owners land |
4232 | if (m_host.OwnerID == World.LandChannel.GetLandObject( | 4233 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4233 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
4234 | { | 4234 | { |
4235 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 4235 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
4236 | } | 4236 | } |
@@ -4434,7 +4434,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4434 | { | 4434 | { |
4435 | if (pushrestricted) | 4435 | if (pushrestricted) |
4436 | { | 4436 | { |
4437 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); | 4437 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); |
4438 | 4438 | ||
4439 | // We didn't find the parcel but region is push restricted so assume it is NOT ok | 4439 | // We didn't find the parcel but region is push restricted so assume it is NOT ok |
4440 | if (targetlandObj == null) | 4440 | if (targetlandObj == null) |
@@ -4449,7 +4449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4449 | } | 4449 | } |
4450 | else | 4450 | else |
4451 | { | 4451 | { |
4452 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); | 4452 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); |
4453 | if (targetlandObj == null) | 4453 | if (targetlandObj == null) |
4454 | { | 4454 | { |
4455 | // We didn't find the parcel but region isn't push restricted so assume it's ok | 4455 | // We didn't find the parcel but region isn't push restricted so assume it's ok |
@@ -4871,8 +4871,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4871 | public LSL_Vector llGetCenterOfMass() | 4871 | public LSL_Vector llGetCenterOfMass() |
4872 | { | 4872 | { |
4873 | m_host.AddScriptLPS(1); | 4873 | m_host.AddScriptLPS(1); |
4874 | Vector3 center = m_host.GetCenterOfMass(); | 4874 | |
4875 | return new LSL_Vector(center.X,center.Y,center.Z); | 4875 | return new LSL_Vector(m_host.GetCenterOfMass()); |
4876 | } | 4876 | } |
4877 | 4877 | ||
4878 | public LSL_List llListSort(LSL_List src, int stride, int ascending) | 4878 | public LSL_List llListSort(LSL_List src, int stride, int ascending) |
@@ -5703,12 +5703,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5703 | } | 5703 | } |
5704 | 5704 | ||
5705 | ILandObject land; | 5705 | ILandObject land; |
5706 | Vector3 pos; | ||
5707 | UUID id = UUID.Zero; | 5706 | UUID id = UUID.Zero; |
5707 | |||
5708 | if (parcel || parcelOwned) | 5708 | if (parcel || parcelOwned) |
5709 | { | 5709 | { |
5710 | pos = m_host.ParentGroup.RootPart.GetWorldPosition(); | 5710 | land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition()); |
5711 | land = World.LandChannel.GetLandObject(pos.X, pos.Y); | ||
5712 | if (land == null) | 5711 | if (land == null) |
5713 | { | 5712 | { |
5714 | id = UUID.Zero; | 5713 | id = UUID.Zero; |
@@ -5734,8 +5733,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5734 | { | 5733 | { |
5735 | if (!regionWide) | 5734 | if (!regionWide) |
5736 | { | 5735 | { |
5737 | pos = ssp.AbsolutePosition; | 5736 | land = World.LandChannel.GetLandObject(ssp.AbsolutePosition); |
5738 | land = World.LandChannel.GetLandObject(pos.X, pos.Y); | ||
5739 | if (land != null) | 5737 | if (land != null) |
5740 | { | 5738 | { |
5741 | if (parcelOwned && land.LandData.OwnerID == id || | 5739 | if (parcelOwned && land.LandData.OwnerID == id || |
@@ -5860,7 +5858,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5860 | if (presence != null) | 5858 | if (presence != null) |
5861 | { | 5859 | { |
5862 | // agent must be over the owners land | 5860 | // agent must be over the owners land |
5863 | ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); | 5861 | ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition); |
5864 | if (land == null) | 5862 | if (land == null) |
5865 | return; | 5863 | return; |
5866 | 5864 | ||
@@ -5882,19 +5880,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5882 | ScenePresence presence = World.GetScenePresence(key); | 5880 | ScenePresence presence = World.GetScenePresence(key); |
5883 | if (presence != null) // object is an avatar | 5881 | if (presence != null) // object is an avatar |
5884 | { | 5882 | { |
5885 | if (m_host.OwnerID | 5883 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
5886 | == World.LandChannel.GetLandObject( | ||
5887 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
5888 | return 1; | 5884 | return 1; |
5889 | } | 5885 | } |
5890 | else // object is not an avatar | 5886 | else // object is not an avatar |
5891 | { | 5887 | { |
5892 | SceneObjectPart obj = World.GetSceneObjectPart(key); | 5888 | SceneObjectPart obj = World.GetSceneObjectPart(key); |
5889 | |||
5893 | if (obj != null) | 5890 | if (obj != null) |
5894 | if (m_host.OwnerID | 5891 | { |
5895 | == World.LandChannel.GetLandObject( | 5892 | if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID) |
5896 | obj.AbsolutePosition.X, obj.AbsolutePosition.Y).LandData.OwnerID) | ||
5897 | return 1; | 5893 | return 1; |
5894 | } | ||
5898 | } | 5895 | } |
5899 | } | 5896 | } |
5900 | 5897 | ||
@@ -5972,8 +5969,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5972 | // if the land is group owned and the object is group owned by the same group | 5969 | // if the land is group owned and the object is group owned by the same group |
5973 | // or | 5970 | // or |
5974 | // if the object is owned by a person with estate access. | 5971 | // if the object is owned by a person with estate access. |
5975 | 5972 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition); | |
5976 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y); | ||
5977 | if (parcel != null) | 5973 | if (parcel != null) |
5978 | { | 5974 | { |
5979 | if (m_host.OwnerID == parcel.LandData.OwnerID || | 5975 | if (m_host.OwnerID == parcel.LandData.OwnerID || |
@@ -5985,14 +5981,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5985 | } | 5981 | } |
5986 | } | 5982 | } |
5987 | } | 5983 | } |
5988 | |||
5989 | } | 5984 | } |
5990 | |||
5991 | } | 5985 | } |
5992 | 5986 | ||
5993 | public LSL_Vector llGroundSlope(LSL_Vector offset) | 5987 | public LSL_Vector llGroundSlope(LSL_Vector offset) |
5994 | { | 5988 | { |
5995 | m_host.AddScriptLPS(1); | 5989 | m_host.AddScriptLPS(1); |
5990 | |||
5996 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. | 5991 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. |
5997 | LSL_Vector vsn = llGroundNormal(offset); | 5992 | LSL_Vector vsn = llGroundNormal(offset); |
5998 | 5993 | ||
@@ -6003,7 +5998,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6003 | vsl.Normalize(); | 5998 | vsl.Normalize(); |
6004 | //Normalization might be overkill here | 5999 | //Normalization might be overkill here |
6005 | 6000 | ||
6006 | return new LSL_Vector(vsl.X, vsl.Y, vsl.Z); | 6001 | vsn.x = vsl.X; |
6002 | vsn.y = vsl.Y; | ||
6003 | vsn.z = vsl.Z; | ||
6004 | |||
6005 | return vsn; | ||
6007 | } | 6006 | } |
6008 | 6007 | ||
6009 | public LSL_Vector llGroundNormal(LSL_Vector offset) | 6008 | public LSL_Vector llGroundNormal(LSL_Vector offset) |
@@ -6053,7 +6052,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6053 | //I believe the crossproduct of two normalized vectors is a normalized vector so | 6052 | //I believe the crossproduct of two normalized vectors is a normalized vector so |
6054 | //this normalization may be overkill | 6053 | //this normalization may be overkill |
6055 | 6054 | ||
6056 | return new LSL_Vector(vsn.X, vsn.Y, vsn.Z); | 6055 | return new LSL_Vector(vsn); |
6057 | } | 6056 | } |
6058 | 6057 | ||
6059 | public LSL_Vector llGroundContour(LSL_Vector offset) | 6058 | public LSL_Vector llGroundContour(LSL_Vector offset) |
@@ -6069,7 +6068,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6069 | return m_host.ParentGroup.AttachmentPoint; | 6068 | return m_host.ParentGroup.AttachmentPoint; |
6070 | } | 6069 | } |
6071 | 6070 | ||
6072 | public LSL_Integer llGetFreeMemory() | 6071 | public virtual LSL_Integer llGetFreeMemory() |
6073 | { | 6072 | { |
6074 | m_host.AddScriptLPS(1); | 6073 | m_host.AddScriptLPS(1); |
6075 | // Make scripts designed for LSO happy | 6074 | // Make scripts designed for LSO happy |
@@ -6553,7 +6552,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6553 | { | 6552 | { |
6554 | m_host.AddScriptLPS(1); | 6553 | m_host.AddScriptLPS(1); |
6555 | UUID key; | 6554 | UUID key; |
6556 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 6555 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
6556 | |||
6557 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 6557 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
6558 | { | 6558 | { |
6559 | int expires = 0; | 6559 | int expires = 0; |
@@ -7782,7 +7782,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7782 | { | 7782 | { |
7783 | m_host.AddScriptLPS(1); | 7783 | m_host.AddScriptLPS(1); |
7784 | 7784 | ||
7785 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 7785 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
7786 | 7786 | ||
7787 | if (land.LandData.OwnerID != m_host.OwnerID) | 7787 | if (land.LandData.OwnerID != m_host.OwnerID) |
7788 | return; | 7788 | return; |
@@ -7796,7 +7796,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7796 | { | 7796 | { |
7797 | m_host.AddScriptLPS(1); | 7797 | m_host.AddScriptLPS(1); |
7798 | 7798 | ||
7799 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 7799 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
7800 | 7800 | ||
7801 | if (land.LandData.OwnerID != m_host.OwnerID) | 7801 | if (land.LandData.OwnerID != m_host.OwnerID) |
7802 | return String.Empty; | 7802 | return String.Empty; |
@@ -7807,8 +7807,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7807 | public LSL_Vector llGetRootPosition() | 7807 | public LSL_Vector llGetRootPosition() |
7808 | { | 7808 | { |
7809 | m_host.AddScriptLPS(1); | 7809 | m_host.AddScriptLPS(1); |
7810 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, | 7810 | |
7811 | m_host.ParentGroup.AbsolutePosition.Z); | 7811 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition); |
7812 | } | 7812 | } |
7813 | 7813 | ||
7814 | /// <summary> | 7814 | /// <summary> |
@@ -7831,13 +7831,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7831 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 7831 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
7832 | q = avatar.CameraRotation; // Mouselook | 7832 | q = avatar.CameraRotation; // Mouselook |
7833 | else | 7833 | else |
7834 | q = avatar.Rotation; // Currently infrequently updated so may be inaccurate | 7834 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate |
7835 | else | 7835 | else |
7836 | q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case | 7836 | q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case |
7837 | } | 7837 | } |
7838 | else | 7838 | else |
7839 | q = m_host.ParentGroup.GroupRotation; // just the group rotation | 7839 | q = m_host.ParentGroup.GroupRotation; // just the group rotation |
7840 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 7840 | |
7841 | return new LSL_Rotation(q); | ||
7841 | } | 7842 | } |
7842 | 7843 | ||
7843 | public LSL_String llGetObjectDesc() | 7844 | public LSL_String llGetObjectDesc() |
@@ -7944,7 +7945,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7944 | 7945 | ||
7945 | public LSL_Vector llGetGeometricCenter() | 7946 | public LSL_Vector llGetGeometricCenter() |
7946 | { | 7947 | { |
7947 | return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); | 7948 | return new LSL_Vector(m_host.GetGeometricCenter()); |
7948 | } | 7949 | } |
7949 | 7950 | ||
7950 | public LSL_List llGetPrimitiveParams(LSL_List rules) | 7951 | public LSL_List llGetPrimitiveParams(LSL_List rules) |
@@ -8031,23 +8032,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8031 | break; | 8032 | break; |
8032 | 8033 | ||
8033 | case (int)ScriptBaseClass.PRIM_POSITION: | 8034 | case (int)ScriptBaseClass.PRIM_POSITION: |
8034 | LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, | 8035 | LSL_Vector v = new LSL_Vector(part.AbsolutePosition); |
8035 | part.AbsolutePosition.Y, | 8036 | |
8036 | part.AbsolutePosition.Z); | ||
8037 | // For some reason, the part.AbsolutePosition.* values do not change if the | 8037 | // For some reason, the part.AbsolutePosition.* values do not change if the |
8038 | // linkset is rotated; they always reflect the child prim's world position | 8038 | // linkset is rotated; they always reflect the child prim's world position |
8039 | // as though the linkset is unrotated. This is incompatible behavior with SL's | 8039 | // as though the linkset is unrotated. This is incompatible behavior with SL's |
8040 | // implementation, so will break scripts imported from there (not to mention it | 8040 | // implementation, so will break scripts imported from there (not to mention it |
8041 | // makes it more difficult to determine a child prim's actual inworld position). | 8041 | // makes it more difficult to determine a child prim's actual inworld position). |
8042 | if (part.ParentID != 0) | 8042 | if (!part.IsRoot) |
8043 | v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition(); | 8043 | { |
8044 | LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition); | ||
8045 | v = ((v - rootPos) * llGetRootRotation()) + rootPos; | ||
8046 | } | ||
8047 | |||
8044 | res.Add(v); | 8048 | res.Add(v); |
8045 | break; | 8049 | break; |
8046 | 8050 | ||
8047 | case (int)ScriptBaseClass.PRIM_SIZE: | 8051 | case (int)ScriptBaseClass.PRIM_SIZE: |
8048 | res.Add(new LSL_Vector(part.Scale.X, | 8052 | res.Add(new LSL_Vector(part.Scale)); |
8049 | part.Scale.Y, | ||
8050 | part.Scale.Z)); | ||
8051 | break; | 8053 | break; |
8052 | 8054 | ||
8053 | case (int)ScriptBaseClass.PRIM_ROTATION: | 8055 | case (int)ScriptBaseClass.PRIM_ROTATION: |
@@ -8361,8 +8363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8361 | case (int)ScriptBaseClass.PRIM_DESC: | 8363 | case (int)ScriptBaseClass.PRIM_DESC: |
8362 | res.Add(new LSL_String(part.Description)); | 8364 | res.Add(new LSL_String(part.Description)); |
8363 | break; | 8365 | break; |
8364 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | 8366 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: |
8365 | res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); | 8367 | res.Add(new LSL_Rotation(part.RotationOffset)); |
8366 | break; | 8368 | break; |
8367 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | 8369 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: |
8368 | res.Add(new LSL_Vector(GetPartLocalPos(part))); | 8370 | res.Add(new LSL_Vector(GetPartLocalPos(part))); |
@@ -9571,7 +9573,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9571 | 9573 | ||
9572 | // according to the docs, this command only works if script owner and land owner are the same | 9574 | // according to the docs, this command only works if script owner and land owner are the same |
9573 | // lets add estate owners and gods, too, and use the generic permission check. | 9575 | // lets add estate owners and gods, too, and use the generic permission check. |
9574 | ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 9576 | ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
9575 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; | 9577 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; |
9576 | 9578 | ||
9577 | bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? | 9579 | bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? |
@@ -9890,21 +9892,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9890 | m_host.AddScriptLPS(1); | 9892 | m_host.AddScriptLPS(1); |
9891 | 9893 | ||
9892 | if (m_item.PermsGranter == UUID.Zero) | 9894 | if (m_item.PermsGranter == UUID.Zero) |
9893 | return new LSL_Vector(); | 9895 | return Vector3.Zero; |
9894 | 9896 | ||
9895 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | 9897 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) |
9896 | { | 9898 | { |
9897 | ShoutError("No permissions to track the camera"); | 9899 | ShoutError("No permissions to track the camera"); |
9898 | return new LSL_Vector(); | 9900 | return Vector3.Zero; |
9899 | } | 9901 | } |
9900 | 9902 | ||
9901 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 9903 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
9902 | if (presence != null) | 9904 | if (presence != null) |
9903 | { | 9905 | { |
9904 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); | 9906 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition); |
9905 | return pos; | 9907 | return pos; |
9906 | } | 9908 | } |
9907 | return new LSL_Vector(); | 9909 | |
9910 | return Vector3.Zero; | ||
9908 | } | 9911 | } |
9909 | 9912 | ||
9910 | public LSL_Rotation llGetCameraRot() | 9913 | public LSL_Rotation llGetCameraRot() |
@@ -9912,21 +9915,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9912 | m_host.AddScriptLPS(1); | 9915 | m_host.AddScriptLPS(1); |
9913 | 9916 | ||
9914 | if (m_item.PermsGranter == UUID.Zero) | 9917 | if (m_item.PermsGranter == UUID.Zero) |
9915 | return new LSL_Rotation(); | 9918 | return Quaternion.Identity; |
9916 | 9919 | ||
9917 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | 9920 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) |
9918 | { | 9921 | { |
9919 | ShoutError("No permissions to track the camera"); | 9922 | ShoutError("No permissions to track the camera"); |
9920 | return new LSL_Rotation(); | 9923 | return Quaternion.Identity; |
9921 | } | 9924 | } |
9922 | 9925 | ||
9923 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 9926 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
9924 | if (presence != null) | 9927 | if (presence != null) |
9925 | { | 9928 | { |
9926 | return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); | 9929 | return new LSL_Rotation(presence.CameraRotation); |
9927 | } | 9930 | } |
9928 | 9931 | ||
9929 | return new LSL_Rotation(); | 9932 | return Quaternion.Identity; |
9930 | } | 9933 | } |
9931 | 9934 | ||
9932 | /// <summary> | 9935 | /// <summary> |
@@ -9995,7 +9998,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9995 | { | 9998 | { |
9996 | m_host.AddScriptLPS(1); | 9999 | m_host.AddScriptLPS(1); |
9997 | UUID key; | 10000 | UUID key; |
9998 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 10001 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
9999 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 10002 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
10000 | { | 10003 | { |
10001 | int expires = 0; | 10004 | int expires = 0; |
@@ -10036,7 +10039,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10036 | { | 10039 | { |
10037 | m_host.AddScriptLPS(1); | 10040 | m_host.AddScriptLPS(1); |
10038 | UUID key; | 10041 | UUID key; |
10039 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 10042 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
10040 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) | 10043 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) |
10041 | { | 10044 | { |
10042 | if (UUID.TryParse(avatar, out key)) | 10045 | if (UUID.TryParse(avatar, out key)) |
@@ -10063,7 +10066,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10063 | { | 10066 | { |
10064 | m_host.AddScriptLPS(1); | 10067 | m_host.AddScriptLPS(1); |
10065 | UUID key; | 10068 | UUID key; |
10066 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 10069 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
10067 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 10070 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
10068 | { | 10071 | { |
10069 | if (UUID.TryParse(avatar, out key)) | 10072 | if (UUID.TryParse(avatar, out key)) |
@@ -10325,7 +10328,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10325 | public void llResetLandBanList() | 10328 | public void llResetLandBanList() |
10326 | { | 10329 | { |
10327 | m_host.AddScriptLPS(1); | 10330 | m_host.AddScriptLPS(1); |
10328 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; | 10331 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
10329 | if (land.OwnerID == m_host.OwnerID) | 10332 | if (land.OwnerID == m_host.OwnerID) |
10330 | { | 10333 | { |
10331 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 10334 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
@@ -10342,7 +10345,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10342 | public void llResetLandPassList() | 10345 | public void llResetLandPassList() |
10343 | { | 10346 | { |
10344 | m_host.AddScriptLPS(1); | 10347 | m_host.AddScriptLPS(1); |
10345 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; | 10348 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
10346 | if (land.OwnerID == m_host.OwnerID) | 10349 | if (land.OwnerID == m_host.OwnerID) |
10347 | { | 10350 | { |
10348 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 10351 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
@@ -10518,7 +10521,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10518 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); | 10521 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); |
10519 | break; | 10522 | break; |
10520 | case ScriptBaseClass.OBJECT_ROT: | 10523 | case ScriptBaseClass.OBJECT_ROT: |
10521 | ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); | 10524 | ret.Add(new LSL_Rotation(av.GetWorldRotation())); |
10522 | break; | 10525 | break; |
10523 | case ScriptBaseClass.OBJECT_VELOCITY: | 10526 | case ScriptBaseClass.OBJECT_VELOCITY: |
10524 | ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); | 10527 | ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); |
@@ -10920,7 +10923,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10920 | 10923 | ||
10921 | LSL_List result = new LSL_List(); | 10924 | LSL_List result = new LSL_List(); |
10922 | 10925 | ||
10923 | if (obj != null && obj.OwnerID != m_host.OwnerID) | 10926 | if (obj != null && obj.OwnerID == m_host.OwnerID) |
10924 | { | 10927 | { |
10925 | LSL_List remaining = GetPrimParams(obj, rules, ref result); | 10928 | LSL_List remaining = GetPrimParams(obj, rules, ref result); |
10926 | 10929 | ||
@@ -11021,7 +11024,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11021 | World.ForEachScenePresence(delegate(ScenePresence sp) | 11024 | World.ForEachScenePresence(delegate(ScenePresence sp) |
11022 | { | 11025 | { |
11023 | Vector3 ac = sp.AbsolutePosition - rayStart; | 11026 | Vector3 ac = sp.AbsolutePosition - rayStart; |
11024 | Vector3 bc = sp.AbsolutePosition - rayEnd; | 11027 | // Vector3 bc = sp.AbsolutePosition - rayEnd; |
11025 | 11028 | ||
11026 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | 11029 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); |
11027 | 11030 | ||
@@ -11111,7 +11114,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11111 | radius = Math.Abs(maxZ); | 11114 | radius = Math.Abs(maxZ); |
11112 | radius = radius*1.413f; | 11115 | radius = radius*1.413f; |
11113 | Vector3 ac = group.AbsolutePosition - rayStart; | 11116 | Vector3 ac = group.AbsolutePosition - rayStart; |
11114 | Vector3 bc = group.AbsolutePosition - rayEnd; | 11117 | // Vector3 bc = group.AbsolutePosition - rayEnd; |
11115 | 11118 | ||
11116 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | 11119 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); |
11117 | 11120 | ||
@@ -11455,7 +11458,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11455 | list.Add(new LSL_Integer(linkNum)); | 11458 | list.Add(new LSL_Integer(linkNum)); |
11456 | 11459 | ||
11457 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) | 11460 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) |
11458 | list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z)); | 11461 | list.Add(new LSL_Vector(result.Normal)); |
11459 | 11462 | ||
11460 | values++; | 11463 | values++; |
11461 | if (values >= count) | 11464 | if (values >= count) |
@@ -11557,7 +11560,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11557 | return 16384; | 11560 | return 16384; |
11558 | } | 11561 | } |
11559 | 11562 | ||
11560 | public LSL_Integer llGetUsedMemory() | 11563 | public virtual LSL_Integer llGetUsedMemory() |
11561 | { | 11564 | { |
11562 | m_host.AddScriptLPS(1); | 11565 | m_host.AddScriptLPS(1); |
11563 | // The value returned for LSO scripts in SL | 11566 | // The value returned for LSO scripts in SL |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index d0922aa..21bae27 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | |||
@@ -266,6 +266,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
266 | { | 266 | { |
267 | llist[i] = new LSL_Float((float)result[i]); | 267 | llist[i] = new LSL_Float((float)result[i]); |
268 | } | 268 | } |
269 | else if (result[i] is double) | ||
270 | { | ||
271 | llist[i] = new LSL_Float((double)result[i]); | ||
272 | } | ||
269 | else if (result[i] is UUID) | 273 | else if (result[i] is UUID) |
270 | { | 274 | { |
271 | llist[i] = new LSL_Key(result[i].ToString()); | 275 | llist[i] = new LSL_Key(result[i].ToString()); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 48c6b50..bf1b45b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -363,7 +363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
363 | //OSSL only may be used if object is in the same group as the parcel | 363 | //OSSL only may be used if object is in the same group as the parcel |
364 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER")) | 364 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER")) |
365 | { | 365 | { |
366 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 366 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
367 | 367 | ||
368 | if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) | 368 | if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) |
369 | { | 369 | { |
@@ -374,7 +374,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
374 | //Only Parcelowners may use the function | 374 | //Only Parcelowners may use the function |
375 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_OWNER")) | 375 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_OWNER")) |
376 | { | 376 | { |
377 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 377 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
378 | 378 | ||
379 | if (land.LandData.OwnerID == ownerID) | 379 | if (land.LandData.OwnerID == ownerID) |
380 | { | 380 | { |
@@ -1502,8 +1502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1502 | 1502 | ||
1503 | m_host.AddScriptLPS(1); | 1503 | m_host.AddScriptLPS(1); |
1504 | 1504 | ||
1505 | ILandObject land | 1505 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
1506 | = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
1507 | 1506 | ||
1508 | if (land.LandData.OwnerID != m_host.OwnerID) | 1507 | if (land.LandData.OwnerID != m_host.OwnerID) |
1509 | return; | 1508 | return; |
@@ -1519,8 +1518,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1519 | 1518 | ||
1520 | m_host.AddScriptLPS(1); | 1519 | m_host.AddScriptLPS(1); |
1521 | 1520 | ||
1522 | ILandObject land | 1521 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
1523 | = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
1524 | 1522 | ||
1525 | if (land.LandData.OwnerID != m_host.OwnerID) | 1523 | if (land.LandData.OwnerID != m_host.OwnerID) |
1526 | { | 1524 | { |
@@ -2515,13 +2513,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2515 | ScenePresence sp = World.GetScenePresence(npcId); | 2513 | ScenePresence sp = World.GetScenePresence(npcId); |
2516 | 2514 | ||
2517 | if (sp != null) | 2515 | if (sp != null) |
2518 | { | 2516 | return new LSL_Vector(sp.AbsolutePosition); |
2519 | Vector3 pos = sp.AbsolutePosition; | ||
2520 | return new LSL_Vector(pos.X, pos.Y, pos.Z); | ||
2521 | } | ||
2522 | } | 2517 | } |
2523 | 2518 | ||
2524 | return new LSL_Vector(0, 0, 0); | 2519 | return Vector3.Zero; |
2525 | } | 2520 | } |
2526 | 2521 | ||
2527 | public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) | 2522 | public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) |
@@ -2578,21 +2573,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2578 | { | 2573 | { |
2579 | UUID npcId; | 2574 | UUID npcId; |
2580 | if (!UUID.TryParse(npc.m_string, out npcId)) | 2575 | if (!UUID.TryParse(npc.m_string, out npcId)) |
2581 | return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); | 2576 | return new LSL_Rotation(Quaternion.Identity); |
2582 | 2577 | ||
2583 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) | 2578 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) |
2584 | return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); | 2579 | return new LSL_Rotation(Quaternion.Identity); |
2585 | 2580 | ||
2586 | ScenePresence sp = World.GetScenePresence(npcId); | 2581 | ScenePresence sp = World.GetScenePresence(npcId); |
2587 | 2582 | ||
2588 | if (sp != null) | 2583 | if (sp != null) |
2589 | { | 2584 | return new LSL_Rotation(sp.GetWorldRotation()); |
2590 | Quaternion rot = sp.Rotation; | ||
2591 | return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); | ||
2592 | } | ||
2593 | } | 2585 | } |
2594 | 2586 | ||
2595 | return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); | 2587 | return Quaternion.Identity; |
2596 | } | 2588 | } |
2597 | 2589 | ||
2598 | public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation) | 2590 | public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation) |
@@ -3022,20 +3014,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3022 | 3014 | ||
3023 | UUID avatarId = new UUID(avatar); | 3015 | UUID avatarId = new UUID(avatar); |
3024 | ScenePresence presence = World.GetScenePresence(avatarId); | 3016 | ScenePresence presence = World.GetScenePresence(avatarId); |
3025 | Vector3 pos = m_host.GetWorldPosition(); | 3017 | |
3026 | bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.X, (float)pos.Y, (float)pos.Z)); | 3018 | if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition())) |
3027 | if (result) | ||
3028 | { | 3019 | { |
3029 | if (presence != null) | 3020 | float health = presence.Health; |
3030 | { | 3021 | health += (float)healing; |
3031 | float health = presence.Health; | 3022 | |
3032 | health += (float)healing; | 3023 | if (health >= 100) |
3033 | if (health >= 100) | 3024 | health = 100; |
3034 | { | 3025 | |
3035 | health = 100; | 3026 | presence.setHealthWithUpdate(health); |
3036 | } | ||
3037 | presence.setHealthWithUpdate(health); | ||
3038 | } | ||
3039 | } | 3027 | } |
3040 | } | 3028 | } |
3041 | 3029 | ||
@@ -3112,8 +3100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3112 | if (avatar != null && avatar.UUID != m_host.OwnerID) | 3100 | if (avatar != null && avatar.UUID != m_host.OwnerID) |
3113 | { | 3101 | { |
3114 | result.Add(new LSL_String(avatar.UUID.ToString())); | 3102 | result.Add(new LSL_String(avatar.UUID.ToString())); |
3115 | OpenMetaverse.Vector3 ap = avatar.AbsolutePosition; | 3103 | result.Add(new LSL_Vector(avatar.AbsolutePosition)); |
3116 | result.Add(new LSL_Vector(ap.X, ap.Y, ap.Z)); | ||
3117 | result.Add(new LSL_String(avatar.Name)); | 3104 | result.Add(new LSL_String(avatar.Name)); |
3118 | } | 3105 | } |
3119 | }); | 3106 | }); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index dd45406..88ab515 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | |||
@@ -353,7 +353,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
353 | // Position of a sensor in a child prim attached to an avatar | 353 | // Position of a sensor in a child prim attached to an avatar |
354 | // will be still wrong. | 354 | // will be still wrong. |
355 | ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); | 355 | ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); |
356 | q = avatar.Rotation * q; | 356 | q = avatar.GetWorldRotation() * q; |
357 | } | 357 | } |
358 | 358 | ||
359 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); | 359 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); |
@@ -480,7 +480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
480 | // Position of a sensor in a child prim attached to an avatar | 480 | // Position of a sensor in a child prim attached to an avatar |
481 | // will be still wrong. | 481 | // will be still wrong. |
482 | ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); | 482 | ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); |
483 | q = avatar.Rotation * q; | 483 | q = avatar.GetWorldRotation() * q; |
484 | } | 484 | } |
485 | 485 | ||
486 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); | 486 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 9d20c9e..b71afe3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs | |||
@@ -662,13 +662,18 @@ namespace SecondLife | |||
662 | { | 662 | { |
663 | string severity = CompErr.IsWarning ? "Warning" : "Error"; | 663 | string severity = CompErr.IsWarning ? "Warning" : "Error"; |
664 | 664 | ||
665 | KeyValuePair<int, int> lslPos; | 665 | KeyValuePair<int, int> errorPos; |
666 | 666 | ||
667 | // Show 5 errors max, but check entire list for errors | 667 | // Show 5 errors max, but check entire list for errors |
668 | 668 | ||
669 | if (severity == "Error") | 669 | if (severity == "Error") |
670 | { | 670 | { |
671 | lslPos = FindErrorPosition(CompErr.Line, CompErr.Column, m_lineMaps[assembly]); | 671 | // C# scripts will not have a linemap since theres no line translation involved. |
672 | if (!m_lineMaps.ContainsKey(assembly)) | ||
673 | errorPos = new KeyValuePair<int, int>(CompErr.Line, CompErr.Column); | ||
674 | else | ||
675 | errorPos = FindErrorPosition(CompErr.Line, CompErr.Column, m_lineMaps[assembly]); | ||
676 | |||
672 | string text = CompErr.ErrorText; | 677 | string text = CompErr.ErrorText; |
673 | 678 | ||
674 | // Use LSL type names | 679 | // Use LSL type names |
@@ -678,7 +683,7 @@ namespace SecondLife | |||
678 | // The Second Life viewer's script editor begins | 683 | // The Second Life viewer's script editor begins |
679 | // countingn lines and columns at 0, so we subtract 1. | 684 | // countingn lines and columns at 0, so we subtract 1. |
680 | errtext += String.Format("({0},{1}): {4} {2}: {3}\n", | 685 | errtext += String.Format("({0},{1}): {4} {2}: {3}\n", |
681 | lslPos.Key - 1, lslPos.Value - 1, | 686 | errorPos.Key - 1, errorPos.Value - 1, |
682 | CompErr.ErrorNumber, text, severity); | 687 | CompErr.ErrorNumber, text, severity); |
683 | hadErrors = true; | 688 | hadErrors = true; |
684 | } | 689 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs index b0baa1c..ab44e38 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs | |||
@@ -209,7 +209,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
209 | += (itemId, evp) => m_lslApi.llHTTPResponse(evp.Params[0].ToString(), 200, testResponse); | 209 | += (itemId, evp) => m_lslApi.llHTTPResponse(evp.Params[0].ToString(), 200, testResponse); |
210 | 210 | ||
211 | // Console.WriteLine("Trying {0}", returnedUri); | 211 | // Console.WriteLine("Trying {0}", returnedUri); |
212 | HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri); | ||
213 | 212 | ||
214 | AssertHttpResponse(returnedUri, testResponse); | 213 | AssertHttpResponse(returnedUri, testResponse); |
215 | 214 | ||