aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs66
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs25
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs270
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs233
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs79
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Border.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs89
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs74
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs31
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs48
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs3
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs56
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs12
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs158
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs88
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs10
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs158
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs13
31 files changed, 1089 insertions, 396 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index f19e391..e50dac6 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -141,6 +141,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
141 availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod); 141 availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
142 142
143 // Agent management 143 // Agent management
144 availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
144 availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod); 145 availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
145 146
146 // User management 147 // User management
@@ -1901,6 +1902,71 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1901 m_log.Info("[RADMIN]: Access List List Request complete"); 1902 m_log.Info("[RADMIN]: Access List List Request complete");
1902 } 1903 }
1903 1904
1905 private void XmlRpcGetAgentsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
1906 {
1907 Hashtable responseData = (Hashtable)response.Value;
1908 Hashtable requestData = (Hashtable)request.Params[0];
1909
1910 bool includeChildren = false;
1911
1912 if (requestData.Contains("include_children"))
1913 bool.TryParse((string)requestData["include_children"], out includeChildren);
1914
1915 Scene scene;
1916 GetSceneFromRegionParams(requestData, responseData, out scene);
1917
1918 ArrayList xmlRpcRegions = new ArrayList();
1919 responseData["regions"] = xmlRpcRegions;
1920
1921 Hashtable xmlRpcRegion = new Hashtable();
1922 xmlRpcRegions.Add(xmlRpcRegion);
1923
1924 xmlRpcRegion["name"] = scene.Name;
1925 xmlRpcRegion["id"] = scene.RegionInfo.RegionID.ToString();
1926
1927 List<ScenePresence> agents = scene.GetScenePresences();
1928 ArrayList xmlrpcAgents = new ArrayList();
1929
1930 foreach (ScenePresence agent in agents)
1931 {
1932 if (agent.IsChildAgent && !includeChildren)
1933 continue;
1934
1935 Hashtable xmlRpcAgent = new Hashtable();
1936 xmlRpcAgent.Add("name", agent.Name);
1937 xmlRpcAgent.Add("id", agent.UUID.ToString());
1938 xmlRpcAgent.Add("type", agent.PresenceType.ToString());
1939 xmlRpcAgent.Add("current_parcel_id", agent.currentParcelUUID.ToString());
1940
1941 Vector3 pos = agent.AbsolutePosition;
1942 xmlRpcAgent.Add("pos_x", pos.X.ToString());
1943 xmlRpcAgent.Add("pos_y", pos.Y.ToString());
1944 xmlRpcAgent.Add("pos_z", pos.Z.ToString());
1945
1946 Vector3 lookAt = agent.Lookat;
1947 xmlRpcAgent.Add("lookat_x", lookAt.X.ToString());
1948 xmlRpcAgent.Add("lookat_y", lookAt.Y.ToString());
1949 xmlRpcAgent.Add("lookat_z", lookAt.Z.ToString());
1950
1951 Vector3 vel = agent.Velocity;
1952 xmlRpcAgent.Add("vel_x", vel.X.ToString());
1953 xmlRpcAgent.Add("vel_y", vel.Y.ToString());
1954 xmlRpcAgent.Add("vel_z", vel.Z.ToString());
1955
1956 xmlRpcAgent.Add("is_flying", agent.Flying.ToString());
1957 xmlRpcAgent.Add("is_sat_on_ground", agent.SitGround.ToString());
1958 xmlRpcAgent.Add("is_sat_on_object", agent.IsSatOnObject.ToString());
1959
1960 xmlrpcAgents.Add(xmlRpcAgent);
1961 }
1962
1963 m_log.DebugFormat(
1964 "[REMOTE ADMIN]: XmlRpcGetAgents found {0} agents in {1}", xmlrpcAgents.Count, scene.Name);
1965
1966 xmlRpcRegion["agents"] = xmlrpcAgents;
1967 responseData["success"] = true;
1968 }
1969
1904 private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 1970 private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
1905 { 1971 {
1906 Hashtable responseData = (Hashtable)response.Value; 1972 Hashtable responseData = (Hashtable)response.Value;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index f6e501d..37285e3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -97,6 +97,14 @@ namespace OpenSim.Region.ClientStack.Linden
97 + " >= 1 - turns on outgoing event logging\n" 97 + " >= 1 - turns on outgoing event logging\n"
98 + " >= 2 - turns on poll notification", 98 + " >= 2 - turns on poll notification",
99 HandleDebugEq); 99 HandleDebugEq);
100
101 MainConsole.Instance.Commands.AddCommand(
102 "Debug",
103 false,
104 "show eq",
105 "show eq",
106 "Show contents of event queues for logged in avatars. Used for debugging.",
107 HandleShowEq);
100 } 108 }
101 109
102 public void RemoveRegion(Scene scene) 110 public void RemoveRegion(Scene scene)
@@ -138,7 +146,7 @@ namespace OpenSim.Region.ClientStack.Linden
138 146
139 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) 147 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
140 { 148 {
141 MainConsole.Instance.OutputFormat("Usage: debug eq [0|1]"); 149 MainConsole.Instance.OutputFormat("Usage: debug eq [0|1|2]");
142 } 150 }
143 else 151 else
144 { 152 {
@@ -148,6 +156,21 @@ namespace OpenSim.Region.ClientStack.Linden
148 } 156 }
149 } 157 }
150 158
159 protected void HandleShowEq(string module, string[] args)
160 {
161 MainConsole.Instance.OutputFormat("For scene {0}", m_scene.Name);
162
163 lock (queues)
164 {
165 foreach (KeyValuePair<UUID, Queue<OSD>> kvp in queues)
166 {
167 MainConsole.Instance.OutputFormat(
168 "For agent {0} there are {1} messages queued for send.",
169 kvp.Key, kvp.Value.Count);
170 }
171 }
172 }
173
151 /// <summary> 174 /// <summary>
152 /// Always returns a valid queue 175 /// Always returns a valid queue
153 /// </summary> 176 /// </summary>
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 6ef8815..7d9f935 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -70,6 +70,7 @@ namespace OpenSim.Region.ClientStack.Linden
70 70
71 private string m_MapImageServerURL = string.Empty; 71 private string m_MapImageServerURL = string.Empty;
72 private string m_SearchURL = string.Empty; 72 private string m_SearchURL = string.Empty;
73 private bool m_ExportSupported = false;
73 74
74 #region ISharedRegionModule Members 75 #region ISharedRegionModule Members
75 76
@@ -87,6 +88,8 @@ namespace OpenSim.Region.ClientStack.Linden
87 } 88 }
88 89
89 m_SearchURL = config.GetString("SearchServerURI", string.Empty); 90 m_SearchURL = config.GetString("SearchServerURI", string.Empty);
91
92 m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported);
90 } 93 }
91 94
92 AddDefaultFeatures(); 95 AddDefaultFeatures();
@@ -152,6 +155,9 @@ namespace OpenSim.Region.ClientStack.Linden
152 if (m_SearchURL != string.Empty) 155 if (m_SearchURL != string.Empty)
153 gridServicesMap["search"] = m_SearchURL; 156 gridServicesMap["search"] = m_SearchURL;
154 m_features["GridServices"] = gridServicesMap; 157 m_features["GridServices"] = gridServicesMap;
158
159 if (m_ExportSupported)
160 m_features["ExportSupported"] = true;
155 } 161 }
156 } 162 }
157 163
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index f62512e..cb724aa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
49 { 49 {
50 #region INonSharedRegionModule 50 #region INonSharedRegionModule
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 public int DebugLevel { get; set; }
52 54
53 private Scene m_scene; 55 private Scene m_scene;
54 private IInventoryAccessModule m_invAccessModule; 56 private IInventoryAccessModule m_invAccessModule;
@@ -76,10 +78,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
76 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
77 79
78 if (Enabled) 80 if (Enabled)
81 {
79 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
85
86 MainConsole.Instance.Commands.AddCommand(
87 "Debug",
88 false,
89 "debug attachments",
90 "debug attachments [0|1]",
91 "Turn on attachments debugging\n"
92 + " <= 0 - turns off debugging\n"
93 + " >= 1 - turns on attachment message logging\n",
94 HandleDebugAttachments);
95 }
80 96
81 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 97 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
82 } 98 }
99
100 private void HandleDebugAttachments(string module, string[] args)
101 {
102 int debugLevel;
103
104 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
105 {
106 MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]");
107 }
108 else
109 {
110 DebugLevel = debugLevel;
111 MainConsole.Instance.OutputFormat(
112 "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.Name);
113 }
114 }
115
116 /// <summary>
117 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
118 /// </summary>
119 /// <param name='localID'></param>
120 /// <param name='itemID'></param>
121 private void HandleScriptStateChange(uint localID, bool started)
122 {
123 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID);
124 if (sog != null && sog.IsAttachment)
125 {
126 if (!started)
127 {
128 // FIXME: This is a convoluted way for working out whether the script state has changed to stop
129 // because it has been manually stopped or because the stop was called in UpdateDetachedObject() below
130 // This needs to be handled in a less tangled way.
131 ScenePresence sp = m_scene.GetScenePresence(sog.AttachedAvatar);
132 if (sp.ControllingClient.IsActive)
133 sog.HasGroupChanged = true;
134 }
135 else
136 {
137 sog.HasGroupChanged = true;
138 }
139 }
140 }
83 141
84 public void RemoveRegion(Scene scene) 142 public void RemoveRegion(Scene scene)
85 { 143 {
@@ -153,10 +211,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
153 } 211 }
154 } 212 }
155 213
156 /// <summary>
157 /// RezAttachments. This should only be called upon login on the first region.
158 /// Attachment rezzings on crossings and TPs are done in a different way.
159 /// </summary>
160 public void RezAttachments(IScenePresence sp) 214 public void RezAttachments(IScenePresence sp)
161 { 215 {
162 if (!Enabled) 216 if (!Enabled)
@@ -165,10 +219,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
165 if (null == sp.Appearance) 219 if (null == sp.Appearance)
166 { 220 {
167 m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID); 221 m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID);
222
168 return; 223 return;
169 } 224 }
170 225
171// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name); 226 if (sp.GetAttachments().Count > 0)
227 {
228 if (DebugLevel > 0)
229 m_log.DebugFormat(
230 "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments",
231 m_scene.Name, sp.Name);
232
233 return;
234 }
235
236 if (DebugLevel > 0)
237 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
172 238
173 XmlDocument doc = new XmlDocument(); 239 XmlDocument doc = new XmlDocument();
174 string stateData = String.Empty; 240 string stateData = String.Empty;
@@ -235,10 +301,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
235 301
236 // If we're an NPC then skip all the item checks and manipulations since we don't have an 302 // If we're an NPC then skip all the item checks and manipulations since we don't have an
237 // inventory right now. 303 // inventory right now.
238 if (sp.PresenceType == PresenceType.Npc) 304 RezSingleAttachmentFromInventoryInternal(
239 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null, true); 305 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null);
240 else
241 RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80, d);
242 } 306 }
243 catch (Exception e) 307 catch (Exception e)
244 { 308 {
@@ -254,7 +318,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
254 if (!Enabled) 318 if (!Enabled)
255 return; 319 return;
256 320
257// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); 321 if (DebugLevel > 0)
322 m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
258 323
259 List<SceneObjectGroup> attachments = sp.GetAttachments(); 324 List<SceneObjectGroup> attachments = sp.GetAttachments();
260 325
@@ -287,9 +352,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
287 if (!Enabled) 352 if (!Enabled)
288 return; 353 return;
289 354
290// m_log.DebugFormat( 355 if (DebugLevel > 0)
291// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", 356 m_log.DebugFormat(
292// m_scene.RegionInfo.RegionName, sp.Name, silent); 357 "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
358 m_scene.RegionInfo.RegionName, sp.Name, silent);
293 359
294 foreach (SceneObjectGroup sop in sp.GetAttachments()) 360 foreach (SceneObjectGroup sop in sp.GetAttachments())
295 { 361 {
@@ -299,12 +365,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
299 sp.ClearAttachments(); 365 sp.ClearAttachments();
300 } 366 }
301 367
302 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append) 368 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
303 { 369 {
304 if (!Enabled) 370 if (!Enabled)
305 return false; 371 return false;
306 372
307 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, false, append); 373 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
308 } 374 }
309 375
310 /// <summary> 376 /// <summary>
@@ -315,9 +381,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
315 /// <param name='group'>The object to attach.</param> 381 /// <param name='group'>The object to attach.</param>
316 /// <param name='attachmentPt'></param> 382 /// <param name='attachmentPt'></param>
317 /// <param name='silent'></param> 383 /// <param name='silent'></param>
318 /// <param name='temp'></param> 384 /// <param name='addToInventory'>If true then add object to user inventory.</param>
319 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> 385 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
320 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool resumeScripts, bool append) 386 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
321 { 387 {
322// m_log.DebugFormat( 388// m_log.DebugFormat(
323// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 389// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
@@ -334,9 +400,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
334 400
335 if (group.GetSittingAvatarsCount() != 0) 401 if (group.GetSittingAvatarsCount() != 0)
336 { 402 {
337// m_log.WarnFormat( 403 if (DebugLevel > 0)
338// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", 404 m_log.WarnFormat(
339// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); 405 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
406 group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
340 407
341 return false; 408 return false;
342 } 409 }
@@ -372,6 +439,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
372 439
373 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 440 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
374 441
442 if (attachments.Contains(group))
443 {
444 if (DebugLevel > 0)
445 m_log.WarnFormat(
446 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
447 group.Name, group.LocalId, sp.Name, attachmentPt);
448
449 return false;
450 }
451
375 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones 452 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
376 while (attachments.Count >= 5) 453 while (attachments.Count >= 5)
377 { 454 {
@@ -395,8 +472,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
395 group.AttachmentPoint = attachmentPt; 472 group.AttachmentPoint = attachmentPt;
396 group.AbsolutePosition = attachPos; 473 group.AbsolutePosition = attachPos;
397 474
398 if (sp.PresenceType != PresenceType.Npc) 475 if (addToInventory && sp.PresenceType != PresenceType.Npc)
399 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append); 476 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
400 477
401 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 478 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
402 479
@@ -415,17 +492,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
415 return true; 492 return true;
416 } 493 }
417 494
418 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp, bool append) 495 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool append)
419 { 496 {
420 // Add the new attachment to inventory if we don't already have it. 497 // Add the new attachment to inventory if we don't already have it.
421 if (!temp) 498 UUID newAttachmentItemID = group.FromItemID;
422 { 499 if (newAttachmentItemID == UUID.Zero)
423 UUID newAttachmentItemID = group.FromItemID; 500 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
424 if (newAttachmentItemID == UUID.Zero)
425 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
426 501
427 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 502 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
428 }
429 } 503 }
430 504
431 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 505 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
@@ -438,40 +512,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
438 if (!Enabled) 512 if (!Enabled)
439 return null; 513 return null;
440 514
441// m_log.DebugFormat( 515 if (DebugLevel > 0)
442// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}", 516 m_log.DebugFormat(
443// (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); 517 "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
444 518 (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
445 bool append = (AttachmentPt & 0x80) != 0;
446 AttachmentPt &= 0x7f;
447 519
448 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). 520 // We check the attachments in the avatar appearance here rather than the objects attached to the
449 // This often happens during login - not sure the exact reason. 521 // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are
450 // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the 522 // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done
451 // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login 523 // because pre-outfit folder viewers (most version 1 viewers) require it.
452 // before anything has actually been attached.
453 bool alreadyOn = false; 524 bool alreadyOn = false;
454 List<SceneObjectGroup> existingAttachments = sp.GetAttachments(); 525 List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments();
455 foreach (SceneObjectGroup so in existingAttachments) 526 foreach (AvatarAttachment existingAttachment in existingAttachments)
456 { 527 {
457 if (so.FromItemID == itemID) 528 if (existingAttachment.ItemID == itemID)
458 { 529 {
459 alreadyOn = true; 530 alreadyOn = true;
460 break; 531 break;
461 } 532 }
462 } 533 }
463 534
464// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
465 if (alreadyOn) 535 if (alreadyOn)
466 { 536 {
467// m_log.WarnFormat( 537 if (DebugLevel > 0)
468// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", 538 m_log.DebugFormat(
469// sp.Name, itemID, AttachmentPt); 539 "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
540 sp.Name, itemID, AttachmentPt);
470 541
471 return null; 542 return null;
472 } 543 }
473 544
474 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc, append); 545 bool append = (AttachmentPt & 0x80) != 0;
546 AttachmentPt &= 0x7f;
547
548 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
475 } 549 }
476 550
477 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 551 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -479,7 +553,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
479 if (!Enabled) 553 if (!Enabled)
480 return; 554 return;
481 555
482 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); 556 if (DebugLevel > 0)
557 m_log.DebugFormat(
558 "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}",
559 rezlist.Count, sp.Name, m_scene.Name);
483 560
484 foreach (KeyValuePair<UUID, uint> rez in rezlist) 561 foreach (KeyValuePair<UUID, uint> rez in rezlist)
485 { 562 {
@@ -497,9 +574,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
497 if (!Enabled) 574 if (!Enabled)
498 return; 575 return;
499 576
500// m_log.DebugFormat( 577 if (DebugLevel > 0)
501// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", 578 m_log.DebugFormat(
502// sp.UUID, soLocalId); 579 "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
580 sp.UUID, soLocalId);
503 581
504 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); 582 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
505 583
@@ -515,9 +593,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
515 if (inventoryID == UUID.Zero) 593 if (inventoryID == UUID.Zero)
516 return; 594 return;
517 595
518// m_log.DebugFormat( 596 if (DebugLevel > 0)
519// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", 597 m_log.DebugFormat(
520// so.Name, so.LocalId, inventoryID); 598 "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
599 so.Name, so.LocalId, inventoryID);
521 600
522 lock (sp.AttachmentsSyncLock) 601 lock (sp.AttachmentsSyncLock)
523 { 602 {
@@ -572,9 +651,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
572 return; 651 return;
573 } 652 }
574 653
575// m_log.DebugFormat( 654 if (DebugLevel > 0)
576// "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", 655 m_log.DebugFormat(
577// so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); 656 "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
657 so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
578 658
579 // Scripts MUST be snapshotted before the object is 659 // Scripts MUST be snapshotted before the object is
580 // removed from the scene because doing otherwise will 660 // removed from the scene because doing otherwise will
@@ -700,12 +780,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
700 780
701 grp.HasGroupChanged = false; // Prevent it being saved over and over 781 grp.HasGroupChanged = false; // Prevent it being saved over and over
702 } 782 }
703// else 783 else if (DebugLevel > 0)
704// { 784 {
705// m_log.DebugFormat( 785 m_log.DebugFormat(
706// "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", 786 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
707// grp.UUID, grp.AttachmentPoint); 787 grp.UUID, grp.AttachmentPoint);
708// } 788 }
709 } 789 }
710 790
711 /// <summary> 791 /// <summary>
@@ -723,9 +803,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
723 private void AttachToAgent( 803 private void AttachToAgent(
724 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 804 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
725 { 805 {
726// m_log.DebugFormat( 806 if (DebugLevel > 0)
727// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 807 m_log.DebugFormat(
728// so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 808 "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
809 so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
729 810
730 so.DetachFromBackup(); 811 so.DetachFromBackup();
731 812
@@ -750,9 +831,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
750 { 831 {
751 if (so.HasPrivateAttachmentPoint) 832 if (so.HasPrivateAttachmentPoint)
752 { 833 {
753// m_log.DebugFormat( 834 if (DebugLevel > 0)
754// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", 835 m_log.DebugFormat(
755// so.Name, sp.Name, so.AttachmentPoint); 836 "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
837 so.Name, sp.Name, so.AttachmentPoint);
756 838
757 // As this scene object can now only be seen by the attaching avatar, tell everybody else in the 839 // As this scene object can now only be seen by the attaching avatar, tell everybody else in the
758 // scene that it's no longer in their awareness. 840 // scene that it's no longer in their awareness.
@@ -786,9 +868,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
786 if (m_invAccessModule == null) 868 if (m_invAccessModule == null)
787 return null; 869 return null;
788 870
789 // m_log.DebugFormat( 871 if (DebugLevel > 0)
790 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 872 m_log.DebugFormat(
791 // grp.Name, grp.LocalId, remoteClient.Name); 873 "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
874 grp.Name, grp.LocalId, sp.Name);
792 875
793 InventoryItemBase newItem 876 InventoryItemBase newItem
794 = m_invAccessModule.CopyToInventory( 877 = m_invAccessModule.CopyToInventory(
@@ -872,7 +955,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
872 } 955 }
873 956
874 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 957 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
875 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc, bool append) 958 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
876 { 959 {
877 if (m_invAccessModule == null) 960 if (m_invAccessModule == null)
878 return null; 961 return null;
@@ -897,6 +980,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
897 return null; 980 return null;
898 } 981 }
899 982
983 if (DebugLevel > 0)
984 m_log.DebugFormat(
985 "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
986 objatt.Name, sp.Name, attachmentPt, m_scene.Name);
987
900 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 988 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
901 objatt.HasGroupChanged = false; 989 objatt.HasGroupChanged = false;
902 bool tainted = false; 990 bool tainted = false;
@@ -917,7 +1005,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
917 objatt.ResetOwnerChangeFlag(); 1005 objatt.ResetOwnerChangeFlag();
918 } 1006 }
919 1007
920 AttachObjectInternal(sp, objatt, attachmentPt, false, true, false, true, append); 1008 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
921 } 1009 }
922 catch (Exception e) 1010 catch (Exception e)
923 { 1011 {
@@ -971,9 +1059,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
971 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID); 1059 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
972 if (changed && m_scene.AvatarFactory != null) 1060 if (changed && m_scene.AvatarFactory != null)
973 { 1061 {
974// m_log.DebugFormat( 1062 if (DebugLevel > 0)
975// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()", 1063 m_log.DebugFormat(
976// sp.Name, att.Name, AttachmentPt); 1064 "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
1065 sp.Name, att.Name, AttachmentPt);
977 1066
978 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 1067 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
979 } 1068 }
@@ -988,9 +1077,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
988 if (!Enabled) 1077 if (!Enabled)
989 return null; 1078 return null;
990 1079
991 // m_log.DebugFormat( 1080 if (DebugLevel > 0)
992 // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", 1081 m_log.DebugFormat(
993 // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); 1082 "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
1083 (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
994 1084
995 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1085 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
996 1086
@@ -1021,9 +1111,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1021 1111
1022 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) 1112 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
1023 { 1113 {
1024// m_log.DebugFormat( 1114 if (DebugLevel > 0)
1025// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})", 1115 m_log.DebugFormat(
1026// objectLocalID, remoteClient.Name, AttachmentPt, silent); 1116 "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
1117 objectLocalID, remoteClient.Name, AttachmentPt, silent);
1027 1118
1028 if (!Enabled) 1119 if (!Enabled)
1029 return; 1120 return;
@@ -1056,11 +1147,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1056 AttachmentPt &= 0x7f; 1147 AttachmentPt &= 0x7f;
1057 1148
1058 // Calls attach with a Zero position 1149 // Calls attach with a Zero position
1059 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false, append)) 1150 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, false, append))
1060 { 1151 {
1061// m_log.Debug( 1152 if (DebugLevel > 0)
1062// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 1153 m_log.Debug(
1063// + ", AttachmentPoint: " + AttachmentPt); 1154 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
1155 + ", AttachmentPoint: " + AttachmentPt);
1064 1156
1065 // Save avatar attachment information 1157 // Save avatar attachment information
1066 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1158 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index a8fe045..1a38619 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -130,7 +130,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
130 config.AddConfig("Modules"); 130 config.AddConfig("Modules");
131 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); 131 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
132 132
133 modules.Add(new AttachmentsModule()); 133 AttachmentsModule attMod = new AttachmentsModule();
134 attMod.DebugLevel = 1;
135 modules.Add(attMod);
134 modules.Add(new BasicInventoryAccessModule()); 136 modules.Add(new BasicInventoryAccessModule());
135 } 137 }
136 138
@@ -197,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 199 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 200
199 m_numberOfAttachEventsFired = 0; 201 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false); 202 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
201 203
202 // Check status on scene presence 204 // Check status on scene presence
203 Assert.That(sp.HasAttachments(), Is.True); 205 Assert.That(sp.HasAttachments(), Is.True);
@@ -244,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
244 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); 246 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
245 247
246 m_numberOfAttachEventsFired = 0; 248 m_numberOfAttachEventsFired = 0;
247 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, false, false, false); 249 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false);
248 250
249 // Check status on scene presence 251 // Check status on scene presence
250 Assert.That(sp.HasAttachments(), Is.True); 252 Assert.That(sp.HasAttachments(), Is.True);
@@ -277,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
277 279
278 // Test wearing a different attachment from the ground. 280 // Test wearing a different attachment from the ground.
279 { 281 {
280 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false, false, false); 282 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
281 283
282 // Check status on scene presence 284 // Check status on scene presence
283 Assert.That(sp.HasAttachments(), Is.True); 285 Assert.That(sp.HasAttachments(), Is.True);
@@ -310,7 +312,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
310 312
311 // Test rewearing an already worn attachment from ground. Nothing should happen. 313 // Test rewearing an already worn attachment from ground. Nothing should happen.
312 { 314 {
313 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false, false, false); 315 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
314 316
315 // Check status on scene presence 317 // Check status on scene presence
316 Assert.That(sp.HasAttachments(), Is.True); 318 Assert.That(sp.HasAttachments(), Is.True);
@@ -368,7 +370,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
368 sp2.AbsolutePosition = new Vector3(0, 0, 0); 370 sp2.AbsolutePosition = new Vector3(0, 0, 0);
369 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 371 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
370 372
371 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false); 373 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
372 374
373 Assert.That(sp.HasAttachments(), Is.False); 375 Assert.That(sp.HasAttachments(), Is.False);
374 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 376 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -728,7 +730,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
728 public void TestRezAttachmentsOnAvatarEntrance() 730 public void TestRezAttachmentsOnAvatarEntrance()
729 { 731 {
730 TestHelpers.InMethod(); 732 TestHelpers.InMethod();
731// log4net.Config.XmlConfigurator.Configure(); 733// TestHelpers.EnableLogging();
732 734
733 Scene scene = CreateTestScene(); 735 Scene scene = CreateTestScene();
734 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 736 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 6c9fd86..a34f2d2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -154,7 +154,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
154 154
155 void OnIncomingInstantMessage(GridInstantMessage im) 155 void OnIncomingInstantMessage(GridInstantMessage im)
156 { 156 {
157 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) 157 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport
158 || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport)
158 { 159 {
159 UUID sessionID = new UUID(im.imSessionID); 160 UUID sessionID = new UUID(im.imSessionID);
160 161
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index f3adb95..0c64f19 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)presence.AbsolutePosition.Z + 2); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("[LURE]: TP invite with message {0}", message); 168 m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m; 170 GridInstantMessage m;
171 171
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 25334b9..8082c1b 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Capabilities; 34using OpenSim.Framework.Capabilities;
35using OpenSim.Framework.Client; 35using OpenSim.Framework.Client;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
@@ -77,6 +78,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
77 /// </remarks> 78 /// </remarks>
78 public bool DisableInterRegionTeleportCancellation { get; set; } 79 public bool DisableInterRegionTeleportCancellation { get; set; }
79 80
81 /// <summary>
82 /// Number of times inter-region teleport was attempted.
83 /// </summary>
84 private Stat m_interRegionTeleportAttempts;
85
86 /// <summary>
87 /// Number of times inter-region teleport was aborted (due to simultaneous client logout).
88 /// </summary>
89 private Stat m_interRegionTeleportAborts;
90
91 /// <summary>
92 /// Number of times inter-region teleport was successfully cancelled by the client.
93 /// </summary>
94 private Stat m_interRegionTeleportCancels;
95
96 /// <summary>
97 /// Number of times inter-region teleport failed due to server/client/network problems (e.g. viewer failed to
98 /// connect with destination region).
99 /// </summary>
100 /// <remarks>
101 /// This is not necessarily a problem for this simulator - in open-grid/hg conditions, viewer connectivity to
102 /// destination simulator is unknown.
103 /// </remarks>
104 private Stat m_interRegionTeleportFailures;
105
80 protected bool m_Enabled = false; 106 protected bool m_Enabled = false;
81 107
82 public Scene Scene { get; private set; } 108 public Scene Scene { get; private set; }
@@ -91,6 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
91 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 117 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
92 118
93 private IEventQueue m_eqModule; 119 private IEventQueue m_eqModule;
120 private IRegionCombinerModule m_regionCombinerModule;
94 121
95 #region ISharedRegionModule 122 #region ISharedRegionModule
96 123
@@ -156,6 +183,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
156 183
157 Scene = scene; 184 Scene = scene;
158 185
186 m_interRegionTeleportAttempts =
187 new Stat(
188 "InterRegionTeleportAttempts",
189 "Number of inter-region teleports attempted.",
190 "This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n"
191 + "You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.",
192 "",
193 "entitytransfer",
194 Scene.Name,
195 StatType.Push,
196 null,
197 StatVerbosity.Debug);
198
199 m_interRegionTeleportAborts =
200 new Stat(
201 "InterRegionTeleportAborts",
202 "Number of inter-region teleports aborted due to client actions.",
203 "The chief action is simultaneous logout whilst teleporting.",
204 "",
205 "entitytransfer",
206 Scene.Name,
207 StatType.Push,
208 null,
209 StatVerbosity.Debug);
210
211 m_interRegionTeleportCancels =
212 new Stat(
213 "InterRegionTeleportCancels",
214 "Number of inter-region teleports cancelled by the client.",
215 null,
216 "",
217 "entitytransfer",
218 Scene.Name,
219 StatType.Push,
220 null,
221 StatVerbosity.Debug);
222
223 m_interRegionTeleportFailures =
224 new Stat(
225 "InterRegionTeleportFailures",
226 "Number of inter-region teleports that failed due to server/client/network issues.",
227 "This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.",
228 "",
229 "entitytransfer",
230 Scene.Name,
231 StatType.Push,
232 null,
233 StatVerbosity.Debug);
234
235 StatsManager.RegisterStat(m_interRegionTeleportAttempts);
236 StatsManager.RegisterStat(m_interRegionTeleportAborts);
237 StatsManager.RegisterStat(m_interRegionTeleportCancels);
238 StatsManager.RegisterStat(m_interRegionTeleportFailures);
239
159 scene.RegisterModuleInterface<IEntityTransferModule>(this); 240 scene.RegisterModuleInterface<IEntityTransferModule>(this);
160 scene.EventManager.OnNewClient += OnNewClient; 241 scene.EventManager.OnNewClient += OnNewClient;
161 } 242 }
@@ -173,7 +254,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
173 254
174 public virtual void Close() {} 255 public virtual void Close() {}
175 256
176 public virtual void RemoveRegion(Scene scene) {} 257 public virtual void RemoveRegion(Scene scene)
258 {
259 if (m_Enabled)
260 {
261 StatsManager.DeregisterStat(m_interRegionTeleportAttempts);
262 StatsManager.DeregisterStat(m_interRegionTeleportAborts);
263 StatsManager.DeregisterStat(m_interRegionTeleportCancels);
264 StatsManager.DeregisterStat(m_interRegionTeleportFailures);
265 }
266 }
177 267
178 public virtual void RegionLoaded(Scene scene) 268 public virtual void RegionLoaded(Scene scene)
179 { 269 {
@@ -181,6 +271,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
181 return; 271 return;
182 272
183 m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); 273 m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
274 m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>();
184 } 275 }
185 276
186 #endregion 277 #endregion
@@ -291,8 +382,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
291 Vector3 emergencyPos = new Vector3(128, 128, 128); 382 Vector3 emergencyPos = new Vector3(128, 128, 128);
292 383
293 m_log.WarnFormat( 384 m_log.WarnFormat(
294 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", 385 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}",
295 position, sp.Name, sp.UUID, emergencyPos); 386 position, sp.Name, sp.UUID, Scene.Name, emergencyPos);
296 387
297 position = emergencyPos; 388 position = emergencyPos;
298 } 389 }
@@ -548,6 +639,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
548 return; 639 return;
549 } 640 }
550 641
642 // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
643 // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
644 // as server attempts.
645 m_interRegionTeleportAttempts.Value++;
646
551 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 647 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
552 648
553 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 649 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
@@ -600,6 +696,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
600 bool logout = false; 696 bool logout = false;
601 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 697 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
602 { 698 {
699 m_interRegionTeleportFailures.Value++;
700
603 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); 701 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
604 702
605 m_log.DebugFormat( 703 m_log.DebugFormat(
@@ -611,6 +709,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
611 709
612 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) 710 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
613 { 711 {
712 m_interRegionTeleportCancels.Value++;
713
614 m_log.DebugFormat( 714 m_log.DebugFormat(
615 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 715 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
616 sp.Name, finalDestination.RegionName, sp.Scene.Name); 716 sp.Name, finalDestination.RegionName, sp.Scene.Name);
@@ -619,6 +719,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
619 } 719 }
620 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 720 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
621 { 721 {
722 m_interRegionTeleportAborts.Value++;
723
622 m_log.DebugFormat( 724 m_log.DebugFormat(
623 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", 725 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
624 sp.Name, finalDestination.RegionName, sp.Scene.Name); 726 sp.Name, finalDestination.RegionName, sp.Scene.Name);
@@ -635,6 +737,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
635 IClientIPEndpoint ipepClient; 737 IClientIPEndpoint ipepClient;
636 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 738 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
637 { 739 {
740 m_log.DebugFormat(
741 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
742 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
743
638 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); 744 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
639 #region IP Translation for NAT 745 #region IP Translation for NAT
640 // Uses ipepClient above 746 // Uses ipepClient above
@@ -688,6 +794,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
688 // establish th econnection to the destination which makes it return true. 794 // establish th econnection to the destination which makes it return true.
689 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 795 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
690 { 796 {
797 m_interRegionTeleportAborts.Value++;
798
691 m_log.DebugFormat( 799 m_log.DebugFormat(
692 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", 800 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
693 sp.Name, finalDestination.RegionName, sp.Scene.Name); 801 sp.Name, finalDestination.RegionName, sp.Scene.Name);
@@ -703,6 +811,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
703 { 811 {
704 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 812 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
705 { 813 {
814 m_interRegionTeleportAborts.Value++;
815
706 m_log.DebugFormat( 816 m_log.DebugFormat(
707 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", 817 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
708 sp.Name, finalDestination.RegionName, sp.Scene.Name); 818 sp.Name, finalDestination.RegionName, sp.Scene.Name);
@@ -720,6 +830,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
720 830
721 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) 831 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
722 { 832 {
833 m_interRegionTeleportCancels.Value++;
834
723 m_log.DebugFormat( 835 m_log.DebugFormat(
724 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", 836 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
725 sp.Name, finalDestination.RegionName, sp.Scene.Name); 837 sp.Name, finalDestination.RegionName, sp.Scene.Name);
@@ -755,6 +867,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
755 { 867 {
756 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 868 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
757 { 869 {
870 m_interRegionTeleportAborts.Value++;
871
758 m_log.DebugFormat( 872 m_log.DebugFormat(
759 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", 873 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
760 sp.Name, finalDestination.RegionName, sp.Scene.Name); 874 sp.Name, finalDestination.RegionName, sp.Scene.Name);
@@ -767,6 +881,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
767 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 881 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
768 882
769 Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); 883 Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion.");
884
770 return; 885 return;
771 } 886 }
772 887
@@ -808,15 +923,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
808 // now we have a child agent in this region. 923 // now we have a child agent in this region.
809 sp.Reset(); 924 sp.Reset();
810 } 925 }
811
812 // Commented pending deletion since this method no longer appears to do anything at all
813// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
814// if (sp.Scene.NeedSceneCacheClear(sp.UUID))
815// {
816// m_log.DebugFormat(
817// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
818// sp.UUID);
819// }
820 } 926 }
821 927
822 /// <summary> 928 /// <summary>
@@ -852,6 +958,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
852 { 958 {
853 CleanupFailedInterRegionTeleport(sp, finalDestination); 959 CleanupFailedInterRegionTeleport(sp, finalDestination);
854 960
961 m_interRegionTeleportFailures.Value++;
962
855 sp.ControllingClient.SendTeleportFailed( 963 sp.ControllingClient.SendTeleportFailed(
856 string.Format( 964 string.Format(
857 "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason)); 965 "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason));
@@ -907,7 +1015,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
907 1015
908 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1016 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
909 { 1017 {
910 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1018 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
1019 {
1020 Vector2 swCorner, neCorner;
1021 GetMegaregionViewRange(out swCorner, out neCorner);
1022
1023 m_log.DebugFormat(
1024 "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}",
1025 Scene.Name, swCorner, neCorner, newRegionX, newRegionY);
1026
1027 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1028 }
1029 else
1030 {
1031 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
1032 }
911 } 1033 }
912 1034
913 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 1035 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
@@ -1011,6 +1133,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1011 { 1133 {
1012 version = String.Empty; 1134 version = String.Empty;
1013 newpos = new Vector3(pos.X, pos.Y, pos.Z); 1135 newpos = new Vector3(pos.X, pos.Y, pos.Z);
1136
1137// m_log.DebugFormat(
1138// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1139
1014 uint neighbourx = scene.RegionInfo.RegionLocX; 1140 uint neighbourx = scene.RegionInfo.RegionLocX;
1015 uint neighboury = scene.RegionInfo.RegionLocY; 1141 uint neighboury = scene.RegionInfo.RegionLocY;
1016 const float boundaryDistance = 1.7f; 1142 const float boundaryDistance = 1.7f;
@@ -1182,7 +1308,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1182 Scene initiatingScene) 1308 Scene initiatingScene)
1183 { 1309 {
1184 Thread.Sleep(10000); 1310 Thread.Sleep(10000);
1185 1311
1312 m_log.DebugFormat(
1313 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}",
1314 agent.Name, regionX, regionY, position, initiatingScene.Name);
1315
1316 agent.Scene.RequestTeleportLocation(
1317 agent.ControllingClient,
1318 Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize),
1319 position,
1320 agent.Lookat,
1321 (uint)Constants.TeleportFlags.ViaLocation);
1322
1323 /*
1186 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); 1324 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
1187 if (im != null) 1325 if (im != null)
1188 { 1326 {
@@ -1217,6 +1355,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1217 }); 1355 });
1218 1356
1219 } 1357 }
1358 */
1220 } 1359 }
1221 1360
1222 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar) 1361 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
@@ -1725,6 +1864,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1725 } 1864 }
1726 1865
1727 /// <summary> 1866 /// <summary>
1867 /// Gets the range considered in view of this megaregion (assuming this is a megaregion).
1868 /// </summary>
1869 /// <remarks>Expressed in 256m units</remarks>
1870 /// <param name='swCorner'></param>
1871 /// <param name='neCorner'></param>
1872 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
1873 {
1874 Border[] northBorders = Scene.NorthBorders.ToArray();
1875 Border[] eastBorders = Scene.EastBorders.ToArray();
1876
1877 Vector2 extent = Vector2.Zero;
1878 for (int i = 0; i < eastBorders.Length; i++)
1879 {
1880 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
1881 }
1882 for (int i = 0; i < northBorders.Length; i++)
1883 {
1884 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
1885 }
1886
1887 // Loss of fraction on purpose
1888 extent.X = ((int)extent.X / (int)Constants.RegionSize);
1889 extent.Y = ((int)extent.Y / (int)Constants.RegionSize);
1890
1891 swCorner.X = Scene.RegionInfo.RegionLocX - 1;
1892 swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
1893 neCorner.X = Scene.RegionInfo.RegionLocX + extent.X;
1894 neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y;
1895 }
1896
1897 /// <summary>
1728 /// Return the list of regions that are considered to be neighbours to the given scene. 1898 /// Return the list of regions that are considered to be neighbours to the given scene.
1729 /// </summary> 1899 /// </summary>
1730 /// <param name="pScene"></param> 1900 /// <param name="pScene"></param>
@@ -1736,15 +1906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1736 Scene pScene = avatar.Scene; 1906 Scene pScene = avatar.Scene;
1737 RegionInfo m_regionInfo = pScene.RegionInfo; 1907 RegionInfo m_regionInfo = pScene.RegionInfo;
1738 1908
1739 Border[] northBorders = pScene.NorthBorders.ToArray();
1740 Border[] southBorders = pScene.SouthBorders.ToArray();
1741 Border[] eastBorders = pScene.EastBorders.ToArray();
1742 Border[] westBorders = pScene.WestBorders.ToArray();
1743
1744 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't 1909 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
1745 // clear what should be done with a "far view" given that megaregions already extended the 1910 // clear what should be done with a "far view" given that megaregions already extended the
1746 // view to include everything in the megaregion 1911 // view to include everything in the megaregion
1747 if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) 1912 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
1748 { 1913 {
1749 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; 1914 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
1750 1915
@@ -1762,27 +1927,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1762 } 1927 }
1763 else 1928 else
1764 { 1929 {
1765 Vector2 extent = Vector2.Zero; 1930 Vector2 swCorner, neCorner;
1766 for (int i = 0; i < eastBorders.Length; i++) 1931 GetMegaregionViewRange(out swCorner, out neCorner);
1767 {
1768 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
1769 }
1770 for (int i = 0; i < northBorders.Length; i++)
1771 {
1772 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
1773 }
1774
1775 // Loss of fraction on purpose
1776 extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1;
1777 extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1;
1778
1779 int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize;
1780 int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize;
1781 1932
1782 int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize; 1933 List<GridRegion> neighbours
1783 int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize; 1934 = pScene.GridService.GetRegionRange(
1935 m_regionInfo.ScopeID,
1936 (int)swCorner.X * (int)Constants.RegionSize,
1937 (int)neCorner.X * (int)Constants.RegionSize,
1938 (int)swCorner.Y * (int)Constants.RegionSize,
1939 (int)neCorner.Y * (int)Constants.RegionSize);
1784 1940
1785 List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
1786 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 1941 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
1787 1942
1788 return neighbours; 1943 return neighbours;
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 9b78b3b..d372c0e 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
199 199
200 public override void RemoveRegion(Scene scene) 200 public override void RemoveRegion(Scene scene)
201 { 201 {
202 base.AddRegion(scene); 202 base.RemoveRegion(scene);
203 203
204 if (m_Enabled) 204 if (m_Enabled)
205 scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this); 205 scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 0276267..2b13a8b 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -189,6 +189,45 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
189 case (int)HttpRequestConstants.HTTP_VERIFY_CERT: 189 case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
190 htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0); 190 htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
191 break; 191 break;
192
193 case (int)HttpRequestConstants.HTTP_VERBOSE_THROTTLE:
194
195 // TODO implement me
196 break;
197
198 case (int)HttpRequestConstants.HTTP_CUSTOM_HEADER:
199 //Parameters are in pairs and custom header takes
200 //arguments in pairs so adjust for header marker.
201 ++i;
202
203 //Maximum of 8 headers are allowed based on the
204 //Second Life documentation for llHTTPRequest.
205 for (int count = 1; count <= 8; ++count)
206 {
207 //Not enough parameters remaining for a header?
208 if (parms.Length - i < 2)
209 break;
210
211 //Have we reached the end of the list of headers?
212 //End is marked by a string with a single digit.
213 //We already know we have at least one parameter
214 //so it is safe to do this check at top of loop.
215 if (Char.IsDigit(parms[i][0]))
216 break;
217
218 if (htc.HttpCustomHeaders == null)
219 htc.HttpCustomHeaders = new List<string>();
220
221 htc.HttpCustomHeaders.Add(parms[i]);
222 htc.HttpCustomHeaders.Add(parms[i+1]);
223
224 i += 2;
225 }
226 break;
227
228 case (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE:
229 htc.HttpPragmaNoCache = (int.Parse(parms[i + 1]) != 0);
230 break;
192 } 231 }
193 } 232 }
194 } 233 }
@@ -353,9 +392,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
353 // public const int HTTP_METHOD = 0; 392 // public const int HTTP_METHOD = 0;
354 // public const int HTTP_MIMETYPE = 1; 393 // public const int HTTP_MIMETYPE = 1;
355 // public const int HTTP_VERIFY_CERT = 3; 394 // public const int HTTP_VERIFY_CERT = 3;
395 // public const int HTTP_VERBOSE_THROTTLE = 4;
396 // public const int HTTP_CUSTOM_HEADER = 5;
397 // public const int HTTP_PRAGMA_NO_CACHE = 6;
356 private bool _finished; 398 private bool _finished;
357 public bool Finished 399 public bool Finished
358 { 400 {
359 get { return _finished; } 401 get { return _finished; }
360 } 402 }
361 // public int HttpBodyMaxLen = 2048; // not implemented 403 // public int HttpBodyMaxLen = 2048; // not implemented
@@ -367,9 +409,14 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
367 public bool HttpVerifyCert = true; 409 public bool HttpVerifyCert = true;
368 public IWorkItemResult WorkItem = null; 410 public IWorkItemResult WorkItem = null;
369 411
412 //public bool HttpVerboseThrottle = true; // not implemented
413 public List<string> HttpCustomHeaders = null;
414 public bool HttpPragmaNoCache = true;
415 private Thread httpThread;
416
370 // Request info 417 // Request info
371 private UUID _itemID; 418 private UUID _itemID;
372 public UUID ItemID 419 public UUID ItemID
373 { 420 {
374 get { return _itemID; } 421 get { return _itemID; }
375 set { _itemID = value; } 422 set { _itemID = value; }
@@ -385,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
385 public string proxyexcepts; 432 public string proxyexcepts;
386 public string OutboundBody; 433 public string OutboundBody;
387 private UUID _reqID; 434 private UUID _reqID;
388 public UUID ReqID 435 public UUID ReqID
389 { 436 {
390 get { return _reqID; } 437 get { return _reqID; }
391 set { _reqID = value; } 438 set { _reqID = value; }
@@ -434,20 +481,34 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
434 Request.Method = HttpMethod; 481 Request.Method = HttpMethod;
435 Request.ContentType = HttpMIMEType; 482 Request.ContentType = HttpMIMEType;
436 483
437 if(!HttpVerifyCert) 484 if (!HttpVerifyCert)
438 { 485 {
439 // We could hijack Connection Group Name to identify 486 // We could hijack Connection Group Name to identify
440 // a desired security exception. But at the moment we'll use a dummy header instead. 487 // a desired security exception. But at the moment we'll use a dummy header instead.
441 Request.Headers.Add("NoVerifyCert", "true"); 488 Request.Headers.Add("NoVerifyCert", "true");
442 } 489 }
443 if (proxyurl != null && proxyurl.Length > 0) 490// else
491// {
492// Request.ConnectionGroupName="Verify";
493// }
494 if (!HttpPragmaNoCache)
495 {
496 Request.Headers.Add("Pragma", "no-cache");
497 }
498 if (HttpCustomHeaders != null)
444 { 499 {
445 if (proxyexcepts != null && proxyexcepts.Length > 0) 500 for (int i = 0; i < HttpCustomHeaders.Count; i += 2)
501 Request.Headers.Add(HttpCustomHeaders[i],
502 HttpCustomHeaders[i+1]);
503 }
504 if (proxyurl != null && proxyurl.Length > 0)
505 {
506 if (proxyexcepts != null && proxyexcepts.Length > 0)
446 { 507 {
447 string[] elist = proxyexcepts.Split(';'); 508 string[] elist = proxyexcepts.Split(';');
448 Request.Proxy = new WebProxy(proxyurl, true, elist); 509 Request.Proxy = new WebProxy(proxyurl, true, elist);
449 } 510 }
450 else 511 else
451 { 512 {
452 Request.Proxy = new WebProxy(proxyurl, true); 513 Request.Proxy = new WebProxy(proxyurl, true);
453 } 514 }
@@ -460,7 +521,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
460 Request.Headers[entry.Key] = entry.Value; 521 Request.Headers[entry.Key] = entry.Value;
461 522
462 // Encode outbound data 523 // Encode outbound data
463 if (OutboundBody.Length > 0) 524 if (OutboundBody.Length > 0)
464 { 525 {
465 byte[] data = Util.UTF8.GetBytes(OutboundBody); 526 byte[] data = Util.UTF8.GetBytes(OutboundBody);
466 527
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index 28db407..e434b2e 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -597,6 +597,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
597 cdl.AddRow("LightFalloff", s.LightFalloff); 597 cdl.AddRow("LightFalloff", s.LightFalloff);
598 cdl.AddRow("LightIntensity", s.LightIntensity); 598 cdl.AddRow("LightIntensity", s.LightIntensity);
599 cdl.AddRow("LightRadius", s.LightRadius); 599 cdl.AddRow("LightRadius", s.LightRadius);
600 cdl.AddRow("Location (relative)", sop.RelativePosition);
600 cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a")); 601 cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a"));
601 cdl.AddRow("PathBegin", s.PathBegin); 602 cdl.AddRow("PathBegin", s.PathBegin);
602 cdl.AddRow("PathEnd", s.PathEnd); 603 cdl.AddRow("PathEnd", s.PathEnd);
@@ -619,6 +620,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
619 cdl.AddRow("ProjectionFocus", s.ProjectionFocus); 620 cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
620 cdl.AddRow("ProjectionFOV", s.ProjectionFOV); 621 cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
621 cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID); 622 cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
623 cdl.AddRow("Rotation (Relative)", sop.RotationOffset);
624 cdl.AddRow("Rotation (World)", sop.GetWorldRotation());
622 cdl.AddRow("Scale", s.Scale); 625 cdl.AddRow("Scale", s.Scale);
623 cdl.AddRow( 626 cdl.AddRow(
624 "SculptData", 627 "SculptData",
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index eaaf7a3..3c1247f 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -54,6 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 /// RezAttachments. This should only be called upon login on the first region. 54 /// RezAttachments. This should only be called upon login on the first region.
55 /// Attachment rezzings on crossings and TPs are done in a different way. 55 /// Attachment rezzings on crossings and TPs are done in a different way.
56 /// </summary> 56 /// </summary>
57 /// <remarks>
58 /// This is only actually necessary for viewers which do not have a current outfit folder (these viewers make
59 /// their own attachment calls on login) and agents which have attachments but no viewer (e.g. NPCs).
60 /// </remarks>
57 /// <param name="sp"></param> 61 /// <param name="sp"></param>
58 void RezAttachments(IScenePresence sp); 62 void RezAttachments(IScenePresence sp);
59 63
@@ -77,14 +81,16 @@ namespace OpenSim.Region.Framework.Interfaces
77 void DeleteAttachmentsFromScene(IScenePresence sp, bool silent); 81 void DeleteAttachmentsFromScene(IScenePresence sp, bool silent);
78 82
79 /// <summary> 83 /// <summary>
80 /// Attach an object to an avatar 84 /// Attach an object to an avatar.
81 /// </summary> 85 /// </summary>
82 /// <param name="sp"></param> 86 /// <param name="sp"></param>
83 /// <param name="grp"></param> 87 /// <param name="grp"></param>
84 /// <param name="AttachmentPt"></param> 88 /// <param name="AttachmentPt"></param>
85 /// <param name="silent"></param> 89 /// <param name="silent"></param>
90 /// <param name="addToInventory">If true then add object to user inventory</param>
91 /// <param name="append">Append to attachment point rather than replace.</param>
86 /// <returns>true if the object was successfully attached, false otherwise</returns> 92 /// <returns>true if the object was successfully attached, false otherwise</returns>
87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp, bool append); 93 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool addToInventory, bool append);
88 94
89 /// <summary> 95 /// <summary>
90 /// Rez an attachment from user inventory and change inventory status to match. 96 /// Rez an attachment from user inventory and change inventory status to match.
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index de0f2a3..eb6c5ac 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -36,6 +36,9 @@ namespace OpenSim.Region.Framework.Interfaces
36 HTTP_MIMETYPE = 1, 36 HTTP_MIMETYPE = 1,
37 HTTP_BODY_MAXLENGTH = 2, 37 HTTP_BODY_MAXLENGTH = 2,
38 HTTP_VERIFY_CERT = 3, 38 HTTP_VERIFY_CERT = 3,
39 HTTP_VERBOSE_THROTTLE = 4,
40 HTTP_CUSTOM_HEADER = 5,
41 HTTP_PRAGMA_NO_CACHE = 6
39 } 42 }
40 43
41 public interface IHttpRequestModule 44 public interface IHttpRequestModule
diff --git a/OpenSim/Region/Framework/Scenes/Border.cs b/OpenSim/Region/Framework/Scenes/Border.cs
index c6a6511..08c0c31 100644
--- a/OpenSim/Region/Framework/Scenes/Border.cs
+++ b/OpenSim/Region/Framework/Scenes/Border.cs
@@ -33,8 +33,7 @@ using OpenMetaverse;
33namespace OpenSim.Region.Framework.Scenes 33namespace OpenSim.Region.Framework.Scenes
34{ 34{
35 public class Border 35 public class Border
36 { 36 {
37
38 /// <summary> 37 /// <summary>
39 /// Line perpendicular to the Direction Cardinal. Z value is the 38 /// Line perpendicular to the Direction Cardinal. Z value is the
40 /// </summary> 39 /// </summary>
@@ -81,6 +80,10 @@ namespace OpenSim.Region.Framework.Scenes
81 TriggerRegionY = triggerRegionY; 80 TriggerRegionY = triggerRegionY;
82 } 81 }
83 82
83 /// <summary>
84 /// Tests to see if the given position would cross this border.
85 /// </summary>
86 /// <returns></returns>
84 public bool TestCross(Vector3 position) 87 public bool TestCross(Vector3 position)
85 { 88 {
86 bool result = false; 89 bool result = false;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 357a94b..28fce53 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2644,7 +2644,6 @@ namespace OpenSim.Region.Framework.Scenes
2644 2644
2645 } 2645 }
2646 } 2646 }
2647
2648 2647
2649 return null; 2648 return null;
2650 } 2649 }
@@ -2862,7 +2861,10 @@ namespace OpenSim.Region.Framework.Scenes
2862// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); 2861// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition);
2863 2862
2864 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2863 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2865 2864
2865 // We must currently not resume scripts at this stage since AttachmentsModule does not have the
2866 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2867 // We currently do this in Scene.MakeRootAgent() instead.
2866 if (AttachmentsModule != null) 2868 if (AttachmentsModule != null)
2867 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true); 2869 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
2868 } 2870 }
@@ -2979,35 +2981,6 @@ namespace OpenSim.Region.Framework.Scenes
2979 m_eventManager.TriggerOnNewPresence(sp); 2981 m_eventManager.TriggerOnNewPresence(sp);
2980 2982
2981 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 2983 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2982
2983 // The first agent upon login is a root agent by design.
2984 // For this agent we will have to rez the attachments.
2985 // All other AddNewClient calls find aCircuit.child to be true.
2986 if (aCircuit.child == false)
2987 {
2988 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2989 // start the scripts again (since this is done in RezAttachments()).
2990 // XXX: This is convoluted.
2991 sp.IsChildAgent = false;
2992 sp.IsLoggingIn = true;
2993
2994 // We leave a 5 second pause before attempting to rez attachments to avoid a clash with
2995 // version 3 viewers that maybe doing their own attachment rezzing related to their current
2996 // outfit folder on startup. If these operations do clash, then the symptoms are invisible
2997 // attachments until one zooms in on the avatar.
2998 //
2999 // We do not pause if we are launching on the same thread anyway in order to avoid pointlessly
3000 // delaying any attachment related regression tests.
3001 if (AttachmentsModule != null)
3002 Util.FireAndForget(
3003 o =>
3004 {
3005 if (Util.FireAndForgetMethod != FireAndForgetMethod.None)
3006 Thread.Sleep(5000);
3007
3008 AttachmentsModule.RezAttachments(sp);
3009 });
3010 }
3011 } 2984 }
3012 else 2985 else
3013 { 2986 {
@@ -4344,33 +4317,33 @@ namespace OpenSim.Region.Framework.Scenes
4344// } 4317// }
4345// } 4318// }
4346 4319
4347 /// <summary> 4320// /// <summary>
4348 /// Triggered when an agent crosses into this sim. Also happens on initial login. 4321// /// Triggered when an agent crosses into this sim. Also happens on initial login.
4349 /// </summary> 4322// /// </summary>
4350 /// <param name="agentID"></param> 4323// /// <param name="agentID"></param>
4351 /// <param name="position"></param> 4324// /// <param name="position"></param>
4352 /// <param name="isFlying"></param> 4325// /// <param name="isFlying"></param>
4353 public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying) 4326// public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
4354 { 4327// {
4355 ScenePresence presence = GetScenePresence(agentID); 4328// ScenePresence presence = GetScenePresence(agentID);
4356 if (presence != null) 4329// if (presence != null)
4357 { 4330// {
4358 try 4331// try
4359 { 4332// {
4360 presence.MakeRootAgent(position, isFlying); 4333// presence.MakeRootAgent(position, isFlying);
4361 } 4334// }
4362 catch (Exception e) 4335// catch (Exception e)
4363 { 4336// {
4364 m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace); 4337// m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
4365 } 4338// }
4366 } 4339// }
4367 else 4340// else
4368 { 4341// {
4369 m_log.ErrorFormat( 4342// m_log.ErrorFormat(
4370 "[SCENE]: Could not find presence for agent {0} crossing into scene {1}", 4343// "[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
4371 agentID, RegionInfo.RegionName); 4344// agentID, RegionInfo.RegionName);
4372 } 4345// }
4373 } 4346// }
4374 4347
4375 /// <summary> 4348 /// <summary>
4376 /// We've got an update about an agent that sees into this region, 4349 /// We've got an update about an agent that sees into this region,
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index c2f0792..42644dc 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -3743,6 +3743,10 @@ namespace OpenSim.Region.Framework.Scenes
3743 /// <param name="events"></param> 3743 /// <param name="events"></param>
3744 public void SetScriptEvents(UUID scriptid, int events) 3744 public void SetScriptEvents(UUID scriptid, int events)
3745 { 3745 {
3746// m_log.DebugFormat(
3747// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}",
3748// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name);
3749
3746 // scriptEvents oldparts; 3750 // scriptEvents oldparts;
3747 lock (m_scriptEvents) 3751 lock (m_scriptEvents)
3748 { 3752 {
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5ed7b67..0ab267a 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -456,9 +456,9 @@ namespace OpenSim.Region.Framework.Scenes
456 { 456 {
457 m_pos = PhysicsActor.Position; 457 m_pos = PhysicsActor.Position;
458 458
459 //m_log.DebugFormat( 459// m_log.DebugFormat(
460 // "[SCENE PRESENCE]: Set position {0} for {1} in {2} via getting AbsolutePosition!", 460// "[SCENE PRESENCE]: Set position of {0} in {1} to {2} via getting AbsolutePosition!",
461 // m_pos, Name, Scene.RegionInfo.RegionName); 461// Name, Scene.Name, m_pos);
462 } 462 }
463 else 463 else
464 { 464 {
@@ -485,6 +485,9 @@ namespace OpenSim.Region.Framework.Scenes
485 } 485 }
486 set 486 set
487 { 487 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value);
489// Util.PrintCallStack();
490
488 if (PhysicsActor != null) 491 if (PhysicsActor != null)
489 { 492 {
490 try 493 try
@@ -938,8 +941,6 @@ namespace OpenSim.Region.Framework.Scenes
938 "[SCENE]: Upgrading child to root agent for {0} in {1}", 941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
939 Name, m_scene.RegionInfo.RegionName); 942 Name, m_scene.RegionInfo.RegionName);
940 943
941 bool wasChild = IsChildAgent;
942
943 if (ParentUUID != UUID.Zero) 944 if (ParentUUID != UUID.Zero)
944 { 945 {
945 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
@@ -972,6 +973,9 @@ namespace OpenSim.Region.Framework.Scenes
972 IsLoggingIn = false; 973 IsLoggingIn = false;
973 } 974 }
974 975
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
977
978 IsChildAgent = false;
975 979
976 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
977 if (gm != null) 981 if (gm != null)
@@ -1065,6 +1069,13 @@ namespace OpenSim.Region.Framework.Scenes
1065 else 1069 else
1066 AddToPhysicalScene(isFlying); 1070 AddToPhysicalScene(isFlying);
1067 1071
1072 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1073 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1074 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1075 // the value to a negative position which does not trigger the border cross.
1076 // This may not be the best location for this.
1077 CheckForBorderCrossing();
1078
1068 if (ForceFly) 1079 if (ForceFly)
1069 { 1080 {
1070 Flying = true; 1081 Flying = true;
@@ -1085,22 +1096,43 @@ namespace OpenSim.Region.Framework.Scenes
1085 // and it has already rezzed the attachments and started their scripts. 1096 // and it has already rezzed the attachments and started their scripts.
1086 // We do the following only for non-login agents, because their scripts 1097 // We do the following only for non-login agents, because their scripts
1087 // haven't started yet. 1098 // haven't started yet.
1088 lock (m_attachments) 1099 if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
1100 {
1101 // Viewers which have a current outfit folder will actually rez their own attachments. However,
1102 // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
1103 if (Scene.AttachmentsModule != null)
1104 Util.FireAndForget(
1105 o =>
1106 {
1107// if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None)
1108// System.Threading.Thread.Sleep(7000);
1109
1110 Scene.AttachmentsModule.RezAttachments(this);
1111 });
1112 }
1113 else
1089 { 1114 {
1090 if (wasChild && HasAttachments()) 1115 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1116 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1117 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data.
1119 lock (m_attachments)
1091 { 1120 {
1092 m_log.DebugFormat( 1121 if (HasAttachments())
1093 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); 1122 {
1094 1123 m_log.DebugFormat(
1095 // Resume scripts 1124 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1096 Util.FireAndForget(delegate(object x) { 1125
1097 foreach (SceneObjectGroup sog in m_attachments) 1126 // Resume scripts
1098 { 1127 Util.FireAndForget(delegate(object x) {
1099 sog.ScheduleGroupForFullUpdate(); 1128 foreach (SceneObjectGroup sog in m_attachments)
1100 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1129 {
1101 sog.ResumeScripts(); 1130 sog.ScheduleGroupForFullUpdate();
1102 } 1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1103 }); 1132 sog.ResumeScripts();
1133 }
1134 });
1135 }
1104 } 1136 }
1105 } 1137 }
1106 1138
@@ -3121,6 +3153,10 @@ namespace OpenSim.Region.Framework.Scenes
3121 3153
3122 if (!IsInTransit) 3154 if (!IsInTransit)
3123 { 3155 {
3156// m_log.DebugFormat(
3157// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3158// pos2, Name, Scene.Name);
3159
3124 // Checks if where it's headed exists a region 3160 // Checks if where it's headed exists a region
3125 bool needsTransit = false; 3161 bool needsTransit = false;
3126 if (m_scene.TestBorderCross(pos2, Cardinals.W)) 3162 if (m_scene.TestBorderCross(pos2, Cardinals.W))
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index 8740f87..d56e39d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -184,7 +184,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
184 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 184 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
185 } 185 }
186 186
187 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true, true) ? 1 : 0; 187 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, true, true) ? 1 : 0;
188 } 188 }
189 } 189 }
190} 190}
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 5fb74b0..29b39e0 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -116,6 +116,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
116 + "If teleport is true then some extra teleport debug information is logged.\n" 116 + "If teleport is true then some extra teleport debug information is logged.\n"
117 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.", 117 + "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
118 HandleDebugSceneSetCommand); 118 HandleDebugSceneSetCommand);
119
120 scene.AddCommand(
121 "Regions",
122 this, "show borders", "show borders", "Show border information for regions", HandleShowBordersCommand);
123 }
124
125 private void HandleShowBordersCommand(string module, string[] args)
126 {
127 StringBuilder sb = new StringBuilder();
128 sb.AppendFormat("Borders for {0}:\n", m_scene.Name);
129
130 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
131 cdt.AddColumn("Cross Direction", 15);
132 cdt.AddColumn("Line", 34);
133 cdt.AddColumn("Trigger Region", 14);
134
135 foreach (Border b in m_scene.NorthBorders)
136 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
137
138 foreach (Border b in m_scene.EastBorders)
139 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
140
141 foreach (Border b in m_scene.SouthBorders)
142 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
143
144 foreach (Border b in m_scene.WestBorders)
145 cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
146
147 cdt.AddToStringBuilder(sb);
148
149 MainConsole.Instance.Output(sb.ToString());
119 } 150 }
120 151
121 private void HandleDebugSceneGetCommand(string module, string[] args) 152 private void HandleDebugSceneGetCommand(string module, string[] args)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index e208d3a..90c2d9c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -479,7 +479,7 @@ public sealed class BSCharacter : BSPhysObject
479 // The character is out of the known/simulated area. 479 // The character is out of the known/simulated area.
480 // Force the avatar position to be within known. ScenePresence will use the position 480 // Force the avatar position to be within known. ScenePresence will use the position
481 // plus the velocity to decide if the avatar is moving out of the region. 481 // plus the velocity to decide if the avatar is moving out of the region.
482 RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); 482 RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
483 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); 483 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
484 return true; 484 return true;
485 } 485 }
@@ -898,7 +898,7 @@ public sealed class BSCharacter : BSPhysObject
898 // 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.
899 if (PositionSanityCheck(true)) 899 if (PositionSanityCheck(true))
900 { 900 {
901 DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); 901 DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position);
902 entprop.Position = _position; 902 entprop.Position = _position;
903 } 903 }
904 904
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5549984..65df741 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -321,7 +321,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
321 } 321 }
322 } 322 }
323 323
324 internal void ProcessTypeChange(Vehicle pType) 324 public void ProcessTypeChange(Vehicle pType)
325 { 325 {
326 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); 326 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType);
327 // Set Defaults For Type 327 // Set Defaults For Type
@@ -1301,14 +1301,52 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1301 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. 1301 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1302 public void ComputeAngularVerticalAttraction() 1302 public void ComputeAngularVerticalAttraction()
1303 { 1303 {
1304
1304 // If vertical attaction timescale is reasonable 1305 // If vertical attaction timescale is reasonable
1305 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1306 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1306 { 1307 {
1308 // Possible solution derived from a discussion at:
1309 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1310
1311 // Create a rotation that is only the vehicle's rotation around Z
1312 Vector3 currentEuler = Vector3.Zero;
1313 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1314 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1315
1316 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1317 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1318 // Compute the angle between those to vectors.
1319 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1320 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1321
1322 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1323 // TODO: add 'efficiency'.
1324 differenceAngle /= m_verticalAttractionTimescale;
1325
1326 // Create the quaterian representing the correction angle
1327 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1328
1329 // Turn that quaternion into Euler values to make it into velocities to apply.
1330 Vector3 vertContributionV = Vector3.Zero;
1331 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1332 vertContributionV *= -1f;
1333
1334 VehicleRotationalVelocity += vertContributionV;
1335
1336 VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
1337 Prim.LocalID,
1338 differenceAxis,
1339 differenceAngle,
1340 correctionRotation,
1341 vertContributionV);
1342
1343 // ===================================================================
1344 /*
1307 Vector3 vertContributionV = Vector3.Zero; 1345 Vector3 vertContributionV = Vector3.Zero;
1308 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG 1346 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1309 1347
1310 // Take a vector pointing up and convert it from world to vehicle relative coords. 1348 // Take a vector pointing up and convert it from world to vehicle relative coords.
1311 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; 1349 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1312 1350
1313 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) 1351 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1314 // is now: 1352 // is now:
@@ -1334,13 +1372,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1334 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. 1372 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1335 // Correction happens over a number of seconds. 1373 // Correction happens over a number of seconds.
1336 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG 1374 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1375
1376 // The correction happens over the user's time period
1337 vertContributionV /= m_verticalAttractionTimescale; 1377 vertContributionV /= m_verticalAttractionTimescale;
1338 1378
1339 VehicleRotationalVelocity += vertContributionV; 1379 // Rotate the vehicle rotation to the world coordinates.
1380 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1340 1381
1341 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", 1382 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1342 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, 1383 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1343 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); 1384 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1385 */
1344 } 1386 }
1345 } 1387 }
1346 1388
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
index 92d62ff..ee77d6e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
@@ -180,11 +180,14 @@ public static class BSMaterials
180 // Use reflection to set the value in the attribute structure. 180 // Use reflection to set the value in the attribute structure.
181 private static void SetAttributeValue(int matType, string attribName, float val) 181 private static void SetAttributeValue(int matType, string attribName, float val)
182 { 182 {
183 // Get the current attribute values for this material
183 MaterialAttributes thisAttrib = Attributes[matType]; 184 MaterialAttributes thisAttrib = Attributes[matType];
185 // Find the field for the passed attribute name (eg, find field named 'friction')
184 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower()); 186 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
185 if (fieldInfo != null) 187 if (fieldInfo != null)
186 { 188 {
187 fieldInfo.SetValue(thisAttrib, val); 189 fieldInfo.SetValue(thisAttrib, val);
190 // Copy new attributes back to array -- since MaterialAttributes is 'struct', passed by value, not reference.
188 Attributes[matType] = thisAttrib; 191 Attributes[matType] = thisAttrib;
189 } 192 }
190 } 193 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 4d89a88..385ed9e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -142,6 +142,14 @@ public static class BSParam
142 public static float VehicleAngularBankingTimescaleFudge { get; private set; } 142 public static float VehicleAngularBankingTimescaleFudge { get; private set; }
143 public static bool VehicleDebuggingEnabled { get; private set; } 143 public static bool VehicleDebuggingEnabled { get; private set; }
144 144
145 // Convex Hulls
146 public static int CSHullMaxDepthSplit { get; private set; }
147 public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; }
148 public static float CSHullConcavityThresholdPercent { get; private set; }
149 public static float CSHullVolumeConservationThresholdPercent { get; private set; }
150 public static int CSHullMaxVertices { get; private set; }
151 public static float CSHullMaxSkinWidth { get; private set; }
152
145 // Linkset implementation parameters 153 // Linkset implementation parameters
146 public static float LinksetImplementation { get; private set; } 154 public static float LinksetImplementation { get; private set; }
147 public static bool LinkConstraintUseFrameOffset { get; private set; } 155 public static bool LinkConstraintUseFrameOffset { get; private set; }
@@ -195,10 +203,10 @@ public static class BSParam
195 public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj); 203 public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
196 public sealed class ParameterDefn<T> : ParameterDefnBase 204 public sealed class ParameterDefn<T> : ParameterDefnBase
197 { 205 {
198 T defaultValue; 206 private T defaultValue;
199 PSetValue<T> setter; 207 private PSetValue<T> setter;
200 PGetValue<T> getter; 208 private PGetValue<T> getter;
201 PSetOnObject<T> objectSet; 209 private PSetOnObject<T> objectSet;
202 public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter) 210 public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
203 : base(pName, pDesc) 211 : base(pName, pDesc)
204 { 212 {
@@ -215,13 +223,23 @@ public static class BSParam
215 getter = pGetter; 223 getter = pGetter;
216 objectSet = pObjSetter; 224 objectSet = pObjSetter;
217 } 225 }
226 /* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work
227 public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc)
228 : base(pName, pDesc)
229 {
230 defaultValue = pDefault;
231 setter = (s, v) => { loc = v; };
232 getter = (s) => { return loc; };
233 objectSet = null;
234 }
235 */
218 public override void AssignDefault(BSScene s) 236 public override void AssignDefault(BSScene s)
219 { 237 {
220 setter(s, defaultValue); 238 setter(s, defaultValue);
221 } 239 }
222 public override string GetValue(BSScene s) 240 public override string GetValue(BSScene s)
223 { 241 {
224 return String.Format("{0}", getter(s)); 242 return getter(s).ToString();
225 } 243 }
226 public override void SetValue(BSScene s, string valAsString) 244 public override void SetValue(BSScene s, string valAsString)
227 { 245 {
@@ -244,6 +262,7 @@ public static class BSParam
244 try 262 try
245 { 263 {
246 T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString }); 264 T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
265 // Store the parsed value
247 setter(s, setValue); 266 setter(s, setValue);
248 // s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue); 267 // s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
249 } 268 }
@@ -463,7 +482,7 @@ public static class BSParam
463 (s) => { return TerrainImplementation; }, 482 (s) => { return TerrainImplementation; },
464 (s,v) => { TerrainImplementation = v; } ), 483 (s,v) => { TerrainImplementation = v; } ),
465 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" , 484 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
466 3, 485 2,
467 (s) => { return TerrainMeshMagnification; }, 486 (s) => { return TerrainMeshMagnification; },
468 (s,v) => { TerrainMeshMagnification = v; } ), 487 (s,v) => { TerrainMeshMagnification = v; } ),
469 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" , 488 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
@@ -623,6 +642,31 @@ public static class BSParam
623 (s) => { return GlobalContactBreakingThreshold; }, 642 (s) => { return GlobalContactBreakingThreshold; },
624 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ), 643 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
625 644
645 new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy",
646 7,
647 (s) => { return CSHullMaxDepthSplit; },
648 (s,v) => { CSHullMaxDepthSplit = v; } ),
649 new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes",
650 2,
651 (s) => { return CSHullMaxDepthSplitForSimpleShapes; },
652 (s,v) => { CSHullMaxDepthSplitForSimpleShapes = v; } ),
653 new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)",
654 5f,
655 (s) => { return CSHullConcavityThresholdPercent; },
656 (s,v) => { CSHullConcavityThresholdPercent = v; } ),
657 new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)",
658 5f,
659 (s) => { return CSHullVolumeConservationThresholdPercent; },
660 (s,v) => { CSHullVolumeConservationThresholdPercent = v; } ),
661 new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.",
662 32,
663 (s) => { return CSHullMaxVertices; },
664 (s,v) => { CSHullMaxVertices = v; } ),
665 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
666 0,
667 (s) => { return CSHullMaxSkinWidth; },
668 (s,v) => { CSHullMaxSkinWidth = v; } ),
669
626 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", 670 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
627 (float)BSLinkset.LinksetImplementation.Compound, 671 (float)BSLinkset.LinksetImplementation.Compound,
628 (s) => { return LinksetImplementation; }, 672 (s) => { return LinksetImplementation; },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index f953c1e..6bb88c7 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -86,7 +86,7 @@ public abstract class BSPhysObject : PhysicsActor
86 PhysBody = new BulletBody(localID); 86 PhysBody = new BulletBody(localID);
87 PhysShape = new BulletShape(); 87 PhysShape = new BulletShape();
88 88
89 LastAssetBuildFailed = false; 89 PrimAssetState = PrimAssetCondition.Unknown;
90 90
91 // Default material type. Also sets Friction, Restitution and Density. 91 // Default material type. Also sets Friction, Restitution and Density.
92 SetMaterial((int)MaterialAttributes.Material.Wood); 92 SetMaterial((int)MaterialAttributes.Material.Wood);
@@ -133,9 +133,13 @@ public abstract class BSPhysObject : PhysicsActor
133 // Reference to the physical shape (btCollisionShape) of this object 133 // Reference to the physical shape (btCollisionShape) of this object
134 public BulletShape PhysShape; 134 public BulletShape PhysShape;
135 135
136 // 'true' if the mesh's underlying asset failed to build. 136 // The physical representation of the prim might require an asset fetch.
137 // This will keep us from looping after the first time the build failed. 137 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
138 public bool LastAssetBuildFailed { get; set; } 138 public enum PrimAssetCondition
139 {
140 Unknown, Waiting, Failed, Fetched
141 }
142 public PrimAssetCondition PrimAssetState { get; set; }
139 143
140 // The objects base shape information. Null if not a prim type shape. 144 // The objects base shape information. Null if not a prim type shape.
141 public PrimitiveBaseShape BaseShape { get; protected set; } 145 public PrimitiveBaseShape BaseShape { get; protected set; }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 2cbbe9a..6a5461a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -155,7 +155,7 @@ public class BSPrim : BSPhysObject
155 public override PrimitiveBaseShape Shape { 155 public override PrimitiveBaseShape Shape {
156 set { 156 set {
157 BaseShape = value; 157 BaseShape = value;
158 LastAssetBuildFailed = false; 158 PrimAssetState = PrimAssetCondition.Unknown;
159 ForceBodyShapeRebuild(false); 159 ForceBodyShapeRebuild(false);
160 } 160 }
161 } 161 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 05c147d..220fbbc 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -447,17 +447,10 @@ public sealed class BSShapeCollection : IDisposable
447 447
448 // If the prim attributes are simple, this could be a simple Bullet native shape 448 // If the prim attributes are simple, this could be a simple Bullet native shape
449 if (!haveShape 449 if (!haveShape
450 && nativeShapePossible
450 && pbs != null 451 && pbs != null
451 && !pbs.SculptEntry 452 && !pbs.SculptEntry
452 && nativeShapePossible 453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
454 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
455 && pbs.ProfileHollow == 0
456 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
457 && pbs.PathBegin == 0 && pbs.PathEnd == 0
458 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
459 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
460 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
461 { 454 {
462 // Get the scale of any existing shape so we can see if the new shape is same native type and same size. 455 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
463 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; 456 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
@@ -508,6 +501,18 @@ public sealed class BSShapeCollection : IDisposable
508 return ret; 501 return ret;
509 } 502 }
510 503
504 // return 'true' if this shape description does not include any cutting or twisting.
505 private bool PrimHasNoCuts(PrimitiveBaseShape pbs)
506 {
507 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
508 && pbs.ProfileHollow == 0
509 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
510 && pbs.PathBegin == 0 && pbs.PathEnd == 0
511 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
512 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
513 && pbs.PathShearX == 0 && pbs.PathShearY == 0;
514 }
515
511 // return 'true' if the prim's shape was changed. 516 // return 'true' if the prim's shape was changed.
512 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 517 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
513 { 518 {
@@ -518,7 +523,7 @@ public sealed class BSShapeCollection : IDisposable
518 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) 523 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
519 { 524 {
520 // Update prim.BSShape to reference a hull of this shape. 525 // Update prim.BSShape to reference a hull of this shape.
521 ret = GetReferenceToHull(prim,shapeCallback); 526 ret = GetReferenceToHull(prim, shapeCallback);
522 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 527 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
523 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 528 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
524 } 529 }
@@ -699,6 +704,7 @@ public sealed class BSShapeCollection : IDisposable
699 704
700 // See that hull shape exists in the physical world and update prim.BSShape. 705 // See that hull shape exists in the physical world and update prim.BSShape.
701 // We could be creating the hull because scale changed or whatever. 706 // We could be creating the hull because scale changed or whatever.
707 // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
702 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 708 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
703 { 709 {
704 BulletShape newShape; 710 BulletShape newShape;
@@ -717,6 +723,7 @@ public sealed class BSShapeCollection : IDisposable
717 DereferenceShape(prim.PhysShape, shapeCallback); 723 DereferenceShape(prim.PhysShape, shapeCallback);
718 724
719 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); 725 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
726 // It might not have been created if we're waiting for an asset.
720 newShape = VerifyMeshCreated(newShape, prim); 727 newShape = VerifyMeshCreated(newShape, prim);
721 728
722 ReferenceShape(newShape); 729 ReferenceShape(newShape);
@@ -735,13 +742,13 @@ public sealed class BSShapeCollection : IDisposable
735 HullDesc hullDesc; 742 HullDesc hullDesc;
736 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 743 if (Hulls.TryGetValue(newHullKey, out hullDesc))
737 { 744 {
738 // If the hull shape already is created, just use it. 745 // If the hull shape already has been created, just use the one shared instance.
739 newShape = hullDesc.shape.Clone(); 746 newShape = hullDesc.shape.Clone();
740 } 747 }
741 else 748 else
742 { 749 {
743 // Build a new hull in the physical world 750 // Build a new hull in the physical world.
744 // Pass true for physicalness as this creates some sort of bounding box which we don't need 751 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
745 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false); 752 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
746 if (meshData != null) 753 if (meshData != null)
747 { 754 {
@@ -761,15 +768,35 @@ public sealed class BSShapeCollection : IDisposable
761 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 768 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
762 } 769 }
763 770
771 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
772 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
773 {
774 // Simple primitive shapes we know are convex so they are better implemented with
775 // fewer hulls.
776 // Check for simple shape (prim without cuts) and reduce split parameter if so.
777 if (PrimHasNoCuts(pbs))
778 {
779 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
780 }
781 }
782
764 // setup and do convex hull conversion 783 // setup and do convex hull conversion
765 m_hulls = new List<ConvexResult>(); 784 m_hulls = new List<ConvexResult>();
766 DecompDesc dcomp = new DecompDesc(); 785 DecompDesc dcomp = new DecompDesc();
767 dcomp.mIndices = convIndices; 786 dcomp.mIndices = convIndices;
768 dcomp.mVertices = convVertices; 787 dcomp.mVertices = convVertices;
788 dcomp.mDepth = maxDepthSplit;
789 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
790 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
791 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
792 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
769 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); 793 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
770 // create the hull into the _hulls variable 794 // create the hull into the _hulls variable
771 convexBuilder.process(dcomp); 795 convexBuilder.process(dcomp);
772 796
797 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
798 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
799
773 // Convert the vertices and indices for passing to unmanaged. 800 // Convert the vertices and indices for passing to unmanaged.
774 // The hull information is passed as a large floating point array. 801 // The hull information is passed as a large floating point array.
775 // The format is: 802 // The format is:
@@ -904,58 +931,79 @@ public sealed class BSShapeCollection : IDisposable
904 if (newShape.HasPhysicalShape) 931 if (newShape.HasPhysicalShape)
905 return newShape; 932 return newShape;
906 933
907 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 934 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
908 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) 935 // fetched but we end up here again, the meshing of the asset must have failed.
936 // Prevent trying to keep fetching the mesh by declaring failure.
937 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
938 {
939 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
940 PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
941 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
942 }
943 else
909 { 944 {
910 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed); 945 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
911 // This will prevent looping through this code as we keep trying to get the failed shape 946 if (prim.BaseShape.SculptEntry
912 prim.LastAssetBuildFailed = true; 947 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
948 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
949 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
950 )
951 {
952 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
953 // Multiple requestors will know we're waiting for this asset
954 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
913 955
914 BSPhysObject xprim = prim; 956 BSPhysObject xprim = prim;
915 Util.FireAndForget(delegate 957 Util.FireAndForget(delegate
916 {
917 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
918 if (assetProvider != null)
919 { 958 {
920 BSPhysObject yprim = xprim; // probably not necessary, but, just in case. 959 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
921 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) 960 if (assetProvider != null)
922 { 961 {
923 bool assetFound = false; // DEBUG DEBUG 962 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
924 string mismatchIDs = String.Empty; // DEBUG DEBUG 963 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
925 if (asset != null && yprim.BaseShape.SculptEntry)
926 { 964 {
927 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) 965 bool assetFound = false;
966 string mismatchIDs = String.Empty; // DEBUG DEBUG
967 if (asset != null && yprim.BaseShape.SculptEntry)
928 { 968 {
929 yprim.BaseShape.SculptData = asset.Data; 969 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
930 // This will cause the prim to see that the filler shape is not the right 970 {
931 // one and try again to build the object. 971 yprim.BaseShape.SculptData = asset.Data;
932 // No race condition with the normal shape setting since the rebuild is at taint time. 972 // This will cause the prim to see that the filler shape is not the right
933 yprim.ForceBodyShapeRebuild(false /* inTaintTime */); 973 // one and try again to build the object.
934 assetFound = true; 974 // No race condition with the normal shape setting since the rebuild is at taint time.
975 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
976 assetFound = true;
977 }
978 else
979 {
980 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
981 }
935 } 982 }
983 if (assetFound)
984 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
936 else 985 else
937 { 986 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
938 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; 987 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
939 } 988 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
940 }
941 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
942 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
943 989
944 }); 990 });
945 } 991 }
946 else 992 else
947 { 993 {
948 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", 994 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
949 LogHeader, PhysicsScene.Name); 995 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
950 } 996 LogHeader, PhysicsScene.Name);
951 }); 997 }
952 } 998 });
953 else 999 }
954 { 1000 else
955 if (prim.LastAssetBuildFailed)
956 { 1001 {
957 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", 1002 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
958 LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); 1003 {
1004 PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1005 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1006 }
959 } 1007 }
960 } 1008 }
961 1009
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index a60946d..b2fb835 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -132,6 +132,7 @@ public sealed class BSTerrainManager : IDisposable
132 // safe to call Bullet in real time. We hope no one is moving prims around yet. 132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
133 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
134 { 134 {
135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
135 // The ground plane is here to catch things that are trying to drop to negative infinity 136 // The ground plane is here to catch things that are trying to drop to negative infinity
136 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); 137 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
137 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, 138 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
@@ -145,14 +146,18 @@ public sealed class BSTerrainManager : IDisposable
145 m_groundPlane.collisionType = CollisionType.Groundplane; 146 m_groundPlane.collisionType = CollisionType.Groundplane;
146 m_groundPlane.ApplyCollisionMask(PhysicsScene); 147 m_groundPlane.ApplyCollisionMask(PhysicsScene);
147 148
148 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 m_terrains.Add(Vector3.Zero, initialTerrain); 150 lock (m_terrains)
151 {
152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
153 m_terrains.Add(Vector3.Zero, initialTerrain);
154 }
151 } 155 }
152 156
153 // Release all the terrain structures we might have allocated 157 // Release all the terrain structures we might have allocated
154 public void ReleaseGroundPlaneAndTerrain() 158 public void ReleaseGroundPlaneAndTerrain()
155 { 159 {
160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
156 if (m_groundPlane.HasPhysicalBody) 161 if (m_groundPlane.HasPhysicalBody)
157 { 162 {
158 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) 163 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane))
@@ -193,11 +198,16 @@ public sealed class BSTerrainManager : IDisposable
193 // the terrain is added to our parent 198 // the terrain is added to our parent
194 if (MegaRegionParentPhysicsScene is BSScene) 199 if (MegaRegionParentPhysicsScene is BSScene)
195 { 200 {
196 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", 201 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax);
197 BSScene.DetailLogZero, m_worldOffset, m_worldMax); 202 // This looks really odd but this region is passing its terrain to its mega-region root region
198 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain( 203 // and the creation of the terrain must happen on the root region's taint thread and not
199 BSScene.CHILDTERRAIN_ID, localHeightMap, 204 // my taint thread.
200 m_worldOffset, m_worldOffset + DefaultRegionSize, true); 205 ((BSScene)MegaRegionParentPhysicsScene).PostTaintObject("TerrainManager.SetTerrain.Mega-" + m_worldOffset.ToString(), 0, delegate()
206 {
207 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
208 BSScene.CHILDTERRAIN_ID, localHeightMap,
209 m_worldOffset, m_worldOffset + DefaultRegionSize, true /* inTaintTime */);
210 });
201 } 211 }
202 } 212 }
203 else 213 else
@@ -206,16 +216,16 @@ public sealed class BSTerrainManager : IDisposable
206 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); 216 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
207 217
208 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, 218 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
209 m_worldOffset, m_worldOffset + DefaultRegionSize, true); 219 m_worldOffset, m_worldOffset + DefaultRegionSize, true /* inTaintTime */);
210 } 220 }
211 }); 221 });
212 } 222 }
213 223
214 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain 224 // If called for terrain has has not been previously allocated, a new terrain will be built
215 // based on the passed information. The 'id' should be either the terrain id or 225 // based on the passed information. The 'id' should be either the terrain id or
216 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. 226 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
217 // The latter feature is for creating child terrains for mega-regions. 227 // The latter feature is for creating child terrains for mega-regions.
218 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new 228 // If there is an existing terrain body, a new
219 // terrain shape is created and added to the body. 229 // terrain shape is created and added to the body.
220 // This call is most often used to update the heightMap and parameters of the terrain. 230 // This call is most often used to update the heightMap and parameters of the terrain.
221 // (The above does suggest that some simplification/refactoring is in order.) 231 // (The above does suggest that some simplification/refactoring is in order.)
@@ -223,8 +233,8 @@ public sealed class BSTerrainManager : IDisposable
223 private void UpdateTerrain(uint id, float[] heightMap, 233 private void UpdateTerrain(uint id, float[] heightMap,
224 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) 234 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
225 { 235 {
226 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}", 236 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3},inTaintTime={4}",
227 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); 237 BSScene.DetailLogZero, id, minCoords, maxCoords, inTaintTime);
228 238
229 // Find high and low points of passed heightmap. 239 // Find high and low points of passed heightmap.
230 // The min and max passed in is usually the area objects can be in (maximum 240 // The min and max passed in is usually the area objects can be in (maximum
@@ -253,7 +263,7 @@ public sealed class BSTerrainManager : IDisposable
253 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) 263 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
254 { 264 {
255 // There is already a terrain in this spot. Free the old and build the new. 265 // There is already a terrain in this spot. Free the old and build the new.
256 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", 266 DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
257 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); 267 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
258 268
259 // Remove old terrain from the collection 269 // Remove old terrain from the collection
@@ -292,7 +302,7 @@ public sealed class BSTerrainManager : IDisposable
292 if (newTerrainID >= BSScene.CHILDTERRAIN_ID) 302 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
293 newTerrainID = ++m_terrainCount; 303 newTerrainID = ++m_terrainCount;
294 304
295 DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", 305 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
296 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 306 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
297 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); 307 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
298 m_terrains.Add(terrainRegionBase, newTerrainPhys); 308 m_terrains.Add(terrainRegionBase, newTerrainPhys);
@@ -343,37 +353,35 @@ public sealed class BSTerrainManager : IDisposable
343 { 353 {
344 Vector3 ret = pPos; 354 Vector3 ret = pPos;
345 355
356 // First, base addresses are never negative so correct for that possible problem.
357 if (ret.X < 0f || ret.Y < 0f)
358 {
359 ret.X = Util.Clamp<float>(ret.X, 0f, 1000000f);
360 ret.Y = Util.Clamp<float>(ret.Y, 0f, 1000000f);
361 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}",
362 BSScene.DetailLogZero, pPos, ret);
363 }
364
346 // Can't do this function if we don't know about any terrain. 365 // Can't do this function if we don't know about any terrain.
347 if (m_terrains.Count == 0) 366 if (m_terrains.Count == 0)
348 return ret; 367 return ret;
349 368
350 int loopPrevention = 5; 369 int loopPrevention = 10;
351 Vector3 terrainBaseXYZ; 370 Vector3 terrainBaseXYZ;
352 BSTerrainPhys physTerrain; 371 BSTerrainPhys physTerrain;
353 while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ)) 372 while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ))
354 { 373 {
355 // The passed position is not within a known terrain area. 374 // The passed position is not within a known terrain area.
375 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
356 376
357 // First, base addresses are never negative so correct for that possible problem. 377 // Must be off the top of a region. Find an adjacent region to move into.
358 if (ret.X < 0f || ret.Y < 0f) 378 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
359 { 379
360 if (ret.X < 0f) 380 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X));
361 ret.X = 0f; 381 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y));
362 if (ret.Y < 0f) 382 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
363 ret.Y = 0f; 383 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
364 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}",
365 BSScene.DetailLogZero, pPos, ret);
366 }
367 else
368 {
369 // Must be off the top of a region. Find an adjacent region to move into.
370 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
371 384
372 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + DefaultRegionSize.X);
373 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + DefaultRegionSize.Y);
374 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
375 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
376 }
377 if (loopPrevention-- < 0f) 385 if (loopPrevention-- < 0f)
378 { 386 {
379 // The 'while' is a little dangerous so this prevents looping forever if the 387 // The 'while' is a little dangerous so this prevents looping forever if the
@@ -383,6 +391,7 @@ public sealed class BSTerrainManager : IDisposable
383 break; 391 break;
384 } 392 }
385 } 393 }
394
386 return ret; 395 return ret;
387 } 396 }
388 397
@@ -479,11 +488,20 @@ public sealed class BSTerrainManager : IDisposable
479 private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase) 488 private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase)
480 { 489 {
481 Vector3 ret = pTerrainBase; 490 Vector3 ret = pTerrainBase;
491
492 // Can't do this function if we don't know about any terrain.
493 if (m_terrains.Count == 0)
494 return ret;
495
496 // Just some sanity
497 ret.X = Util.Clamp<float>(ret.X, 0f, 1000000f);
498 ret.Y = Util.Clamp<float>(ret.Y, 0f, 1000000f);
482 ret.Z = 0f; 499 ret.Z = 0f;
500
483 lock (m_terrains) 501 lock (m_terrains)
484 { 502 {
485 // Once down to the <0,0> region, we have to be done. 503 // Once down to the <0,0> region, we have to be done.
486 while (ret.X > 0f && ret.Y > 0f) 504 while (ret.X > 0f || ret.Y > 0f)
487 { 505 {
488 if (ret.X > 0f) 506 if (ret.X > 0f)
489 { 507 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index a9cd8a1..2ce1513 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -98,20 +98,20 @@ public sealed class BSTerrainMesh : BSTerrainPhys
98 if (!meshCreationSuccess) 98 if (!meshCreationSuccess)
99 { 99 {
100 // DISASTER!! 100 // DISASTER!!
101 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); 101 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
102 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); 102 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
103 // Something is very messed up and a crash is in our future. 103 // Something is very messed up and a crash is in our future.
104 return; 104 return;
105 } 105 }
106 106
107 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}", 107 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
108 ID, indicesCount, indices.Length, verticesCount, vertices.Length); 108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
109 109
110 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices); 110 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
111 if (!m_terrainShape.HasPhysicalShape) 111 if (!m_terrainShape.HasPhysicalShape)
112 { 112 {
113 // DISASTER!! 113 // DISASTER!!
114 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); 114 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
115 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); 115 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
116 // Something is very messed up and a crash is in our future. 116 // Something is very messed up and a crash is in our future.
117 return; 117 return;
@@ -151,7 +151,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
151 151
152 if (BSParam.UseSingleSidedMeshes) 152 if (BSParam.UseSingleSidedMeshes)
153 { 153 {
154 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial", id); 154 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
155 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); 155 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
156 } 156 }
157 157
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 905540d..7127c73 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -415,18 +415,17 @@ namespace OpenSim.Region.RegionCombinerModule
415 */ 415 */
416 #endregion 416 #endregion
417 417
418 // If we're one region over +x y 418 // If we're one region over +x y (i.e. root region is to the west)
419 //xxx 419 //xxx
420 //xxy 420 //xxy
421 //xxx 421 //xxx
422
423 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY) 422 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
424 { 423 {
425 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene); 424 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
426 break; 425 break;
427 } 426 }
428 427
429 // If we're one region over x +y 428 // If we're one region over x +y (i.e. root region is to the south)
430 //xyx 429 //xyx
431 //xxx 430 //xxx
432 //xxx 431 //xxx
@@ -436,7 +435,7 @@ namespace OpenSim.Region.RegionCombinerModule
436 break; 435 break;
437 } 436 }
438 437
439 // If we're one region over +x +y 438 // If we're one region over +x +y (i.e. root region is to the south-west)
440 //xxy 439 //xxy
441 //xxx 440 //xxx
442 //xxx 441 //xxx
@@ -646,7 +645,6 @@ namespace OpenSim.Region.RegionCombinerModule
646 { 645 {
647 if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2) 646 if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
648 { 647 {
649
650 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize; 648 rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
651 649
652 lock (rootConn.RegionScene.NorthBorders) 650 lock (rootConn.RegionScene.NorthBorders)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index f677cdf..bc35272 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -71,6 +71,7 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
71using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 71using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
72using System.Reflection; 72using System.Reflection;
73using Timer = System.Timers.Timer; 73using Timer = System.Timers.Timer;
74using System.Linq;
74using PermissionMask = OpenSim.Framework.PermissionMask; 75using PermissionMask = OpenSim.Framework.PermissionMask;
75 76
76namespace OpenSim.Region.ScriptEngine.Shared.Api 77namespace OpenSim.Region.ScriptEngine.Shared.Api
@@ -96,8 +97,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
96 /// <summary> 97 /// <summary>
97 /// Used for script sleeps when we are using co-operative script termination. 98 /// Used for script sleeps when we are using co-operative script termination.
98 /// </summary> 99 /// </summary>
99 /// <remarks>null if co-operative script termination is not active</remarks> 100 /// <remarks>null if co-operative script termination is not active</remarks>
100 WaitHandle m_coopSleepHandle; 101 WaitHandle m_coopSleepHandle;
101 102
102 /// <summary> 103 /// <summary>
103 /// The item that hosts this script 104 /// The item that hosts this script
@@ -150,6 +151,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
150 {"TURNLEFT", "Turning Left"}, 151 {"TURNLEFT", "Turning Left"},
151 {"TURNRIGHT", "Turning Right"} 152 {"TURNRIGHT", "Turning Right"}
152 }; 153 };
154 //An array of HTTP/1.1 headers that are not allowed to be used
155 //as custom headers by llHTTPRequest.
156 private string[] HttpStandardHeaders =
157 {
158 "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
159 "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
160 "Connection", "Content-Encoding", "Content-Language",
161 "Content-Length", "Content-Location", "Content-MD5",
162 "Content-Range", "Content-Type", "Date", "ETag", "Expect",
163 "Expires", "From", "Host", "If-Match", "If-Modified-Since",
164 "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
165 "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
166 "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
167 "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
168 "Vary", "Via", "Warning", "WWW-Authenticate"
169 };
153 170
154 public void Initialize( 171 public void Initialize(
155 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle) 172 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
@@ -391,7 +408,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
391 /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number 408 /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number
392 /// of entities, then the entity which corresponds to that linknum is returned. 409 /// of entities, then the entity which corresponds to that linknum is returned.
393 /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then 410 /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then
394 /// null is returned. 411 /// null is returned.
395 /// </param> 412 /// </param>
396 public ISceneEntity GetLinkEntity(int linknum) 413 public ISceneEntity GetLinkEntity(int linknum)
397 { 414 {
@@ -1750,7 +1767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1750 if (tex.FaceTextures[i] != null) 1767 if (tex.FaceTextures[i] != null)
1751 { 1768 {
1752 tex.FaceTextures[i].Shiny = sval; 1769 tex.FaceTextures[i].Shiny = sval;
1753 tex.FaceTextures[i].Bump = bump;; 1770 tex.FaceTextures[i].Bump = bump;
1754 } 1771 }
1755 tex.DefaultTexture.Shiny = sval; 1772 tex.DefaultTexture.Shiny = sval;
1756 tex.DefaultTexture.Bump = bump; 1773 tex.DefaultTexture.Bump = bump;
@@ -1873,7 +1890,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1873 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); 1890 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1874 tex.DefaultTexture.RGBA = texcolor; 1891 tex.DefaultTexture.RGBA = texcolor;
1875 } 1892 }
1876 1893
1877 part.UpdateTextureEntry(tex.GetBytes()); 1894 part.UpdateTextureEntry(tex.GetBytes());
1878 return; 1895 return;
1879 } 1896 }
@@ -1996,7 +2013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1996 rgb.x = texcolor.R; 2013 rgb.x = texcolor.R;
1997 rgb.y = texcolor.G; 2014 rgb.y = texcolor.G;
1998 rgb.z = texcolor.B; 2015 rgb.z = texcolor.B;
1999 2016
2000 return rgb; 2017 return rgb;
2001 } 2018 }
2002 else 2019 else
@@ -2038,12 +2055,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2038 2055
2039 UUID textureID = new UUID(); 2056 UUID textureID = new UUID();
2040 2057
2041 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); 2058 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
2042 if (textureID == UUID.Zero) 2059 if (textureID == UUID.Zero)
2043 { 2060 {
2044 if (!UUID.TryParse(texture, out textureID)) 2061 if (!UUID.TryParse(texture, out textureID))
2045 return; 2062 return;
2046 } 2063 }
2047 2064
2048 Primitive.TextureEntry tex = part.Shape.Textures; 2065 Primitive.TextureEntry tex = part.Shape.Textures;
2049 2066
@@ -2249,7 +2266,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2249 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. 2266 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
2250 // 2267 //
2251 // This workaround is to prevent silent failure of this function. 2268 // This workaround is to prevent silent failure of this function.
2252 // According to the specification on the SL Wiki, providing a position outside of the 2269 // According to the specification on the SL Wiki, providing a position outside of the
2253 if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize) 2270 if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize)
2254 { 2271 {
2255 return 0; 2272 return 0;
@@ -2484,7 +2501,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2484 { 2501 {
2485 return llGetRootRotation(); 2502 return llGetRootRotation();
2486 } 2503 }
2487 2504
2488 m_host.AddScriptLPS(1); 2505 m_host.AddScriptLPS(1);
2489 Quaternion q = m_host.GetWorldRotation(); 2506 Quaternion q = m_host.GetWorldRotation();
2490 2507
@@ -3317,7 +3334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3317 3334
3318 if (!UUID.TryParse(id, out objectID)) 3335 if (!UUID.TryParse(id, out objectID))
3319 objectID = UUID.Zero; 3336 objectID = UUID.Zero;
3320 3337
3321 if (objectID == UUID.Zero && name == "") 3338 if (objectID == UUID.Zero && name == "")
3322 return; 3339 return;
3323 3340
@@ -3527,19 +3544,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3527 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3544 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3528 3545
3529 Vector3 pos = m_host.AbsolutePosition; 3546 Vector3 pos = m_host.AbsolutePosition;
3530 msg.binaryBucket 3547 msg.binaryBucket
3531 = Util.StringToBytes256( 3548 = Util.StringToBytes256(
3532 "{0}/{1}/{2}/{3}", 3549 "{0}/{1}/{2}/{3}",
3533 World.RegionInfo.RegionName, 3550 World.RegionInfo.RegionName,
3534 (int)Math.Floor(pos.X), 3551 (int)Math.Floor(pos.X),
3535 (int)Math.Floor(pos.Y), 3552 (int)Math.Floor(pos.Y),
3536 (int)Math.Floor(pos.Z)); 3553 (int)Math.Floor(pos.Z));
3537 3554
3538 if (m_TransferModule != null) 3555 if (m_TransferModule != null)
3539 { 3556 {
3540 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 3557 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3541 } 3558 }
3542 3559
3543 ScriptSleep(2000); 3560 ScriptSleep(2000);
3544 } 3561 }
3545 3562
@@ -3664,7 +3681,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3664 public void llRotLookAt(LSL_Rotation target, double strength, double damping) 3681 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3665 { 3682 {
3666 m_host.AddScriptLPS(1); 3683 m_host.AddScriptLPS(1);
3667 3684
3668 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3685 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
3669 // set the rotation of the object, copy that behavior 3686 // set the rotation of the object, copy that behavior
3670 PhysicsActor pa = m_host.PhysActor; 3687 PhysicsActor pa = m_host.PhysActor;
@@ -5458,7 +5475,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5458 // SL spits out an empty string for types other than key & string 5475 // SL spits out an empty string for types other than key & string
5459 // At the time of patching, LSL_Key is currently LSL_String, 5476 // At the time of patching, LSL_Key is currently LSL_String,
5460 // so the OR check may be a little redundant, but it's being done 5477 // so the OR check may be a little redundant, but it's being done
5461 // for completion and should LSL_Key ever be implemented 5478 // for completion and should LSL_Key ever be implemented
5462 // as it's own struct 5479 // as it's own struct
5463 else if (!(src.Data[index] is LSL_String || 5480 else if (!(src.Data[index] is LSL_String ||
5464 src.Data[index] is LSL_Key || 5481 src.Data[index] is LSL_Key ||
@@ -5595,8 +5612,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5595 { 5612 {
5596 m_host.AddScriptLPS(1); 5613 m_host.AddScriptLPS(1);
5597 5614
5598 return string.Join(", ", 5615 return string.Join(", ",
5599 (new List<object>(src.Data)).ConvertAll<string>(o => 5616 (new List<object>(src.Data)).ConvertAll<string>(o =>
5600 { 5617 {
5601 return o.ToString(); 5618 return o.ToString();
5602 }).ToArray()); 5619 }).ToArray());
@@ -6700,7 +6717,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6700 SetParticleSystem(m_host, rules); 6717 SetParticleSystem(m_host, rules);
6701 } 6718 }
6702 6719
6703 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) 6720 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6704 { 6721 {
6705 if (rules.Length == 0) 6722 if (rules.Length == 0)
6706 { 6723 {
@@ -6937,7 +6954,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6937 m_host.OwnerID, m_host.Name, destID, 6954 m_host.OwnerID, m_host.Name, destID,
6938 (byte)InstantMessageDialog.TaskInventoryOffered, 6955 (byte)InstantMessageDialog.TaskInventoryOffered,
6939 false, string.Format("'{0}'", category), 6956 false, string.Format("'{0}'", category),
6940// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 6957// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06
6941// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), 6958// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
6942 folderID, false, pos, 6959 folderID, false, pos,
6943 bucket, false); 6960 bucket, false);
@@ -7056,12 +7073,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7056 public LSL_String llAvatarOnLinkSitTarget(int linknum) 7073 public LSL_String llAvatarOnLinkSitTarget(int linknum)
7057 { 7074 {
7058 m_host.AddScriptLPS(1); 7075 m_host.AddScriptLPS(1);
7059 if(linknum == ScriptBaseClass.LINK_SET || 7076 if(linknum == ScriptBaseClass.LINK_SET ||
7060 linknum == ScriptBaseClass.LINK_ALL_CHILDREN || 7077 linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
7061 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); 7078 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString();
7062 7079
7063 List<SceneObjectPart> parts = GetLinkParts(linknum); 7080 List<SceneObjectPart> parts = GetLinkParts(linknum);
7064 if (parts.Count == 0) return UUID.Zero.ToString(); 7081 if (parts.Count == 0) return UUID.Zero.ToString();
7065 return parts[0].SitTargetAvatar.ToString(); 7082 return parts[0].SitTargetAvatar.ToString();
7066 } 7083 }
7067 7084
@@ -7451,7 +7468,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7451 hollow = 0.70f; 7468 hollow = 0.70f;
7452 } 7469 }
7453 } 7470 }
7454 // Otherwise, hollow is limited to 95%. 7471 // Otherwise, hollow is limited to 95%.
7455 else 7472 else
7456 { 7473 {
7457 if (hollow > 0.95f) 7474 if (hollow > 0.95f)
@@ -8906,16 +8923,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8906 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); 8923 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
8907 8924
8908 // float revolutions 8925 // float revolutions
8909 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); 8926 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
8910 // Slightly inaccurate, because an unsigned byte is being used to represent 8927 // Slightly inaccurate, because an unsigned byte is being used to represent
8911 // the entire range of floating-point values from 1.0 through 4.0 (which is how 8928 // the entire range of floating-point values from 1.0 through 4.0 (which is how
8912 // SL does it). 8929 // SL does it).
8913 // 8930 //
8914 // Using these formulas to store and retrieve PathRevolutions, it is not 8931 // Using these formulas to store and retrieve PathRevolutions, it is not
8915 // possible to use all values between 1.00 and 4.00. For instance, you can't 8932 // possible to use all values between 1.00 and 4.00. For instance, you can't
8916 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you 8933 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
8917 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them 8934 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
8918 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar 8935 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
8919 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. 8936 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
8920 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value 8937 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
8921 // such as 1.10. So, SL must store and retreive the actual user input rather 8938 // such as 1.10. So, SL must store and retreive the actual user input rather
@@ -9199,7 +9216,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9199 case (int)ScriptBaseClass.PRIM_DESC: 9216 case (int)ScriptBaseClass.PRIM_DESC:
9200 res.Add(new LSL_String(part.Description)); 9217 res.Add(new LSL_String(part.Description));
9201 break; 9218 break;
9202 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9219 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
9203 res.Add(new LSL_Rotation(part.RotationOffset)); 9220 res.Add(new LSL_Rotation(part.RotationOffset));
9204 break; 9221 break;
9205 9222
@@ -11127,9 +11144,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11127 IHttpRequestModule httpScriptMod = 11144 IHttpRequestModule httpScriptMod =
11128 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 11145 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
11129 List<string> param = new List<string>(); 11146 List<string> param = new List<string>();
11130 foreach (object o in parameters.Data) 11147 bool ok;
11148 Int32 flag;
11149
11150 for (int i = 0; i < parameters.Data.Length; i += 2)
11131 { 11151 {
11132 param.Add(o.ToString()); 11152 ok = Int32.TryParse(parameters.Data[i].ToString(), out flag);
11153 if (!ok || flag < 0 ||
11154 flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE)
11155 {
11156 throw new ScriptException("Parameter " + i.ToString() + " is an invalid flag");
11157 }
11158
11159 param.Add(parameters.Data[i].ToString()); //Add parameter flag
11160
11161 if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER)
11162 {
11163 param.Add(parameters.Data[i+1].ToString()); //Add parameter value
11164 }
11165 else
11166 {
11167 //Parameters are in pairs and custom header takes
11168 //arguments in pairs so adjust for header marker.
11169 ++i;
11170
11171 //Maximum of 8 headers are allowed based on the
11172 //Second Life documentation for llHTTPRequest.
11173 for (int count = 1; count <= 8; ++count)
11174 {
11175 //Enough parameters remaining for (another) header?
11176 if (parameters.Data.Length - i < 2)
11177 {
11178 //There must be at least one name/value pair for custom header
11179 if (count == 1)
11180 throw new ScriptException("Missing name/value for custom header at parameter " + i.ToString());
11181 break;
11182 }
11183
11184 if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase))
11185 throw new ScriptException("Name is invalid as a custom header at parameter " + i.ToString());
11186
11187 param.Add(parameters.Data[i].ToString());
11188 param.Add(parameters.Data[i+1].ToString());
11189
11190 //Have we reached the end of the list of headers?
11191 //End is marked by a string with a single digit.
11192 if (i+2 >= parameters.Data.Length ||
11193 Char.IsDigit(parameters.Data[i].ToString()[0]))
11194 {
11195 break;
11196 }
11197
11198 i += 2;
11199 }
11200 }
11133 } 11201 }
11134 11202
11135 Vector3 position = m_host.AbsolutePosition; 11203 Vector3 position = m_host.AbsolutePosition;
@@ -11295,12 +11363,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11295 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) 11363 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
11296 { 11364 {
11297 m_host.AddScriptLPS(1); 11365 m_host.AddScriptLPS(1);
11298 11366
11299 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 11367 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
11300 11368
11301 if (lo == null) 11369 if (lo == null)
11302 return 0; 11370 return 0;
11303 11371
11304 IPrimCounts pc = lo.PrimCounts; 11372 IPrimCounts pc = lo.PrimCounts;
11305 11373
11306 if (sim_wide != ScriptBaseClass.FALSE) 11374 if (sim_wide != ScriptBaseClass.FALSE)
@@ -11330,7 +11398,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11330 else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) 11398 else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP)
11331 return 0; // counts not implemented yet 11399 return 0; // counts not implemented yet
11332 } 11400 }
11333 11401
11334 return 0; 11402 return 0;
11335 } 11403 }
11336 11404
@@ -11691,7 +11759,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11691 return ret; 11759 return ret;
11692 } 11760 }
11693 } 11761 }
11694 11762
11695 return new LSL_List(); 11763 return new LSL_List();
11696 } 11764 }
11697 11765
@@ -12071,7 +12139,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12071// Vector3 bc = group.AbsolutePosition - rayEnd; 12139// Vector3 bc = group.AbsolutePosition - rayEnd;
12072 12140
12073 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 12141 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
12074 12142
12075 // Too far off ray, don't bother 12143 // Too far off ray, don't bother
12076 if (d > radius) 12144 if (d > radius)
12077 return; 12145 return;
@@ -12434,7 +12502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12434 else 12502 else
12435 { 12503 {
12436 ScenePresence sp = World.GetScenePresence(result.ConsumerID); 12504 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
12437 /// It it a boy? a girl? 12505 /// It it a boy? a girl?
12438 if (sp != null) 12506 if (sp != null)
12439 itemID = sp.UUID; 12507 itemID = sp.UUID;
12440 } 12508 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index da3b31f..2f8154d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -356,6 +356,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
356 public const int HTTP_MIMETYPE = 1; 356 public const int HTTP_MIMETYPE = 1;
357 public const int HTTP_BODY_MAXLENGTH = 2; 357 public const int HTTP_BODY_MAXLENGTH = 2;
358 public const int HTTP_VERIFY_CERT = 3; 358 public const int HTTP_VERIFY_CERT = 3;
359 public const int HTTP_VERBOSE_THROTTLE = 4;
360 public const int HTTP_CUSTOM_HEADER = 5;
361 public const int HTTP_PRAGMA_NO_CACHE = 6;
359 362
360 public const int PRIM_MATERIAL = 2; 363 public const int PRIM_MATERIAL = 2;
361 public const int PRIM_PHYSICS = 3; 364 public const int PRIM_PHYSICS = 3;
@@ -636,7 +639,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
636 public const int TOUCH_INVALID_FACE = -1; 639 public const int TOUCH_INVALID_FACE = -1;
637 public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0); 640 public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0);
638 public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR; 641 public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR;
639 642
640 // constants for llGetPrimMediaParams/llSetPrimMediaParams 643 // constants for llGetPrimMediaParams/llSetPrimMediaParams
641 public const int PRIM_MEDIA_ALT_IMAGE_ENABLE = 0; 644 public const int PRIM_MEDIA_ALT_IMAGE_ENABLE = 0;
642 public const int PRIM_MEDIA_CONTROLS = 1; 645 public const int PRIM_MEDIA_CONTROLS = 1;
@@ -653,10 +656,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
653 public const int PRIM_MEDIA_WHITELIST = 12; 656 public const int PRIM_MEDIA_WHITELIST = 12;
654 public const int PRIM_MEDIA_PERMS_INTERACT = 13; 657 public const int PRIM_MEDIA_PERMS_INTERACT = 13;
655 public const int PRIM_MEDIA_PERMS_CONTROL = 14; 658 public const int PRIM_MEDIA_PERMS_CONTROL = 14;
656 659
657 public const int PRIM_MEDIA_CONTROLS_STANDARD = 0; 660 public const int PRIM_MEDIA_CONTROLS_STANDARD = 0;
658 public const int PRIM_MEDIA_CONTROLS_MINI = 1; 661 public const int PRIM_MEDIA_CONTROLS_MINI = 1;
659 662
660 public const int PRIM_MEDIA_PERM_NONE = 0; 663 public const int PRIM_MEDIA_PERM_NONE = 0;
661 public const int PRIM_MEDIA_PERM_OWNER = 1; 664 public const int PRIM_MEDIA_PERM_OWNER = 1;
662 public const int PRIM_MEDIA_PERM_GROUP = 2; 665 public const int PRIM_MEDIA_PERM_GROUP = 2;
@@ -689,7 +692,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
689 public const string TEXTURE_PLYWOOD = "89556747-24cb-43ed-920b-47caed15465f"; 692 public const string TEXTURE_PLYWOOD = "89556747-24cb-43ed-920b-47caed15465f";
690 public const string TEXTURE_TRANSPARENT = "8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"; 693 public const string TEXTURE_TRANSPARENT = "8dcd4a48-2d37-4909-9f78-f7a9eb4ef903";
691 public const string TEXTURE_MEDIA = "8b5fec65-8d8d-9dc5-cda8-8fdf2716e361"; 694 public const string TEXTURE_MEDIA = "8b5fec65-8d8d-9dc5-cda8-8fdf2716e361";
692 695
693 // Constants for osGetRegionStats 696 // Constants for osGetRegionStats
694 public const int STATS_TIME_DILATION = 0; 697 public const int STATS_TIME_DILATION = 0;
695 public const int STATS_SIM_FPS = 1; 698 public const int STATS_SIM_FPS = 1;
@@ -742,7 +745,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
742 public static readonly LSLInteger RC_GET_ROOT_KEY = 2; 745 public static readonly LSLInteger RC_GET_ROOT_KEY = 2;
743 public static readonly LSLInteger RC_GET_LINK_NUM = 4; 746 public static readonly LSLInteger RC_GET_LINK_NUM = 4;
744 747
745 public static readonly LSLInteger RCERR_UNKNOWN = -1; 748 public static readonly LSLInteger RCERR_UNKNOWN = -1;
746 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; 749 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
747 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = -3; 750 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = -3;
748 751